Blame libcpu/i386_disasm.c

Packit 032894
/* Disassembler for x86.
Packit 032894
   Copyright (C) 2007, 2008, 2009, 2011 Red Hat, Inc.
Packit 032894
   This file is part of elfutils.
Packit 032894
   Written by Ulrich Drepper <drepper@redhat.com>, 2007.
Packit 032894
Packit 032894
   This file is free software; you can redistribute it and/or modify
Packit 032894
   it under the terms of either
Packit 032894
Packit 032894
     * the GNU Lesser General Public License as published by the Free
Packit 032894
       Software Foundation; either version 3 of the License, or (at
Packit 032894
       your option) any later version
Packit 032894
Packit 032894
   or
Packit 032894
Packit 032894
     * the GNU General Public License as published by the Free
Packit 032894
       Software Foundation; either version 2 of the License, or (at
Packit 032894
       your option) any later version
Packit 032894
Packit 032894
   or both in parallel, as here.
Packit 032894
Packit 032894
   elfutils is distributed in the hope that it will be useful, but
Packit 032894
   WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 032894
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 032894
   General Public License for more details.
Packit 032894
Packit 032894
   You should have received copies of the GNU General Public License and
Packit 032894
   the GNU Lesser General Public License along with this program.  If
Packit 032894
   not, see <http://www.gnu.org/licenses/>.  */
Packit 032894
Packit 032894
#ifdef HAVE_CONFIG_H
Packit 032894
# include <config.h>
Packit 032894
#endif
Packit 032894
Packit 032894
#include <assert.h>
Packit 032894
#include <config.h>
Packit 032894
#include <ctype.h>
Packit 032894
#include <endian.h>
Packit 032894
#include <errno.h>
Packit 032894
#include <gelf.h>
Packit 032894
#include <stddef.h>
Packit 032894
#include <stdint.h>
Packit 032894
#include <stdlib.h>
Packit 032894
#include <string.h>
Packit 032894
Packit 032894
#include "../libebl/libeblP.h"
Packit 032894
Packit 032894
#define MACHINE_ENCODING __LITTLE_ENDIAN
Packit 032894
#include "memory-access.h"
Packit 032894
Packit 032894
Packit 032894
#ifndef MNEFILE
Packit 032894
# define MNEFILE "i386.mnemonics"
Packit 032894
#endif
Packit 032894
Packit 032894
#define MNESTRFIELD(line) MNESTRFIELD1 (line)
Packit 032894
#define MNESTRFIELD1(line) str##line
Packit 032894
static const union mnestr_t
Packit 032894
{
Packit 032894
  struct
Packit 032894
  {
Packit 032894
#define MNE(name) char MNESTRFIELD (__LINE__)[sizeof (#name)];
Packit 032894
#include MNEFILE
Packit 032894
#undef MNE
Packit 032894
  };
Packit 032894
  char str[0];
Packit 032894
} mnestr =
Packit 032894
  {
Packit 032894
    {
Packit 032894
#define MNE(name) #name,
Packit 032894
#include MNEFILE
Packit 032894
#undef MNE
Packit 032894
    }
Packit 032894
  };
Packit 032894
Packit 032894
/* The index can be stored in the instrtab.  */
Packit 032894
enum
Packit 032894
  {
Packit 032894
#define MNE(name) MNE_##name,
Packit 032894
#include MNEFILE
Packit 032894
#undef MNE
Packit 032894
    MNE_INVALID
Packit 032894
  };
Packit 032894
Packit 032894
static const unsigned short int mneidx[] =
Packit 032894
  {
Packit 032894
#define MNE(name) \
Packit 032894
  [MNE_##name] = offsetof (union mnestr_t, MNESTRFIELD (__LINE__)),
Packit 032894
#include MNEFILE
Packit 032894
#undef MNE
Packit 032894
  };
Packit 032894
Packit 032894
Packit 032894
enum
Packit 032894
  {
Packit 032894
    idx_rex_b = 0,
Packit 032894
    idx_rex_x,
Packit 032894
    idx_rex_r,
Packit 032894
    idx_rex_w,
Packit 032894
    idx_rex,
Packit 032894
    idx_cs,
Packit 032894
    idx_ds,
Packit 032894
    idx_es,
Packit 032894
    idx_fs,
Packit 032894
    idx_gs,
Packit 032894
    idx_ss,
Packit 032894
    idx_data16,
Packit 032894
    idx_addr16,
Packit 032894
    idx_rep,
Packit 032894
    idx_repne,
Packit 032894
    idx_lock
Packit 032894
  };
Packit 032894
Packit 032894
enum
Packit 032894
  {
Packit 032894
#define prefbit(pref) has_##pref = 1 << idx_##pref
Packit 032894
    prefbit (rex_b),
Packit 032894
    prefbit (rex_x),
Packit 032894
    prefbit (rex_r),
Packit 032894
    prefbit (rex_w),
Packit 032894
    prefbit (rex),
Packit 032894
    prefbit (cs),
Packit 032894
    prefbit (ds),
Packit 032894
    prefbit (es),
Packit 032894
    prefbit (fs),
Packit 032894
    prefbit (gs),
Packit 032894
    prefbit (ss),
Packit 032894
    prefbit (data16),
Packit 032894
    prefbit (addr16),
Packit 032894
    prefbit (rep),
Packit 032894
    prefbit (repne),
Packit 032894
    prefbit (lock)
Packit 032894
#undef prefbit
Packit 032894
  };
Packit 032894
#define SEGMENT_PREFIXES \
Packit 032894
  (has_cs | has_ds | has_es | has_fs | has_gs | has_ss)
Packit 032894
Packit 032894
#define prefix_cs	0x2e
Packit 032894
#define prefix_ds	0x3e
Packit 032894
#define prefix_es	0x26
Packit 032894
#define prefix_fs	0x64
Packit 032894
#define prefix_gs	0x65
Packit 032894
#define prefix_ss	0x36
Packit 032894
#define prefix_data16	0x66
Packit 032894
#define prefix_addr16	0x67
Packit 032894
#define prefix_rep	0xf3
Packit 032894
#define prefix_repne	0xf2
Packit 032894
#define prefix_lock	0xf0
Packit 032894
Packit 032894
Packit 032894
static const uint8_t known_prefixes[] =
Packit 032894
  {
Packit 032894
#define newpref(pref) [idx_##pref] = prefix_##pref
Packit 032894
    newpref (cs),
Packit 032894
    newpref (ds),
Packit 032894
    newpref (es),
Packit 032894
    newpref (fs),
Packit 032894
    newpref (gs),
Packit 032894
    newpref (ss),
Packit 032894
    newpref (data16),
Packit 032894
    newpref (addr16),
Packit 032894
    newpref (rep),
Packit 032894
    newpref (repne),
Packit 032894
    newpref (lock)
Packit 032894
#undef newpref
Packit 032894
  };
Packit 032894
#define nknown_prefixes (sizeof (known_prefixes) / sizeof (known_prefixes[0]))
Packit 032894
Packit 032894
Packit 032894
#if 0
Packit 032894
static const char *prefix_str[] =
Packit 032894
  {
Packit 032894
#define newpref(pref) [idx_##pref] = #pref
Packit 032894
    newpref (cs),
Packit 032894
    newpref (ds),
Packit 032894
    newpref (es),
Packit 032894
    newpref (fs),
Packit 032894
    newpref (gs),
Packit 032894
    newpref (ss),
Packit 032894
    newpref (data16),
Packit 032894
    newpref (addr16),
Packit 032894
    newpref (rep),
Packit 032894
    newpref (repne),
Packit 032894
    newpref (lock)
Packit 032894
#undef newpref
Packit 032894
  };
Packit 032894
#endif
Packit 032894
Packit 032894
Packit 032894
static const char amd3dnowstr[] =
Packit 032894
#define MNE_3DNOW_PAVGUSB 1
Packit 032894
  "pavgusb\0"
Packit 032894
#define MNE_3DNOW_PFADD (MNE_3DNOW_PAVGUSB + 8)
Packit 032894
  "pfadd\0"
Packit 032894
#define MNE_3DNOW_PFSUB (MNE_3DNOW_PFADD + 6)
Packit 032894
  "pfsub\0"
Packit 032894
#define MNE_3DNOW_PFSUBR (MNE_3DNOW_PFSUB + 6)
Packit 032894
  "pfsubr\0"
Packit 032894
#define MNE_3DNOW_PFACC (MNE_3DNOW_PFSUBR + 7)
Packit 032894
  "pfacc\0"
Packit 032894
#define MNE_3DNOW_PFCMPGE (MNE_3DNOW_PFACC + 6)
Packit 032894
  "pfcmpge\0"
Packit 032894
#define MNE_3DNOW_PFCMPGT (MNE_3DNOW_PFCMPGE + 8)
Packit 032894
  "pfcmpgt\0"
Packit 032894
#define MNE_3DNOW_PFCMPEQ (MNE_3DNOW_PFCMPGT + 8)
Packit 032894
  "pfcmpeq\0"
Packit 032894
#define MNE_3DNOW_PFMIN (MNE_3DNOW_PFCMPEQ + 8)
Packit 032894
  "pfmin\0"
Packit 032894
#define MNE_3DNOW_PFMAX (MNE_3DNOW_PFMIN + 6)
Packit 032894
  "pfmax\0"
Packit 032894
#define MNE_3DNOW_PI2FD (MNE_3DNOW_PFMAX + 6)
Packit 032894
  "pi2fd\0"
Packit 032894
#define MNE_3DNOW_PF2ID (MNE_3DNOW_PI2FD + 6)
Packit 032894
  "pf2id\0"
Packit 032894
#define MNE_3DNOW_PFRCP (MNE_3DNOW_PF2ID + 6)
Packit 032894
  "pfrcp\0"
Packit 032894
#define MNE_3DNOW_PFRSQRT (MNE_3DNOW_PFRCP + 6)
Packit 032894
  "pfrsqrt\0"
Packit 032894
#define MNE_3DNOW_PFMUL (MNE_3DNOW_PFRSQRT + 8)
Packit 032894
  "pfmul\0"
Packit 032894
#define MNE_3DNOW_PFRCPIT1 (MNE_3DNOW_PFMUL + 6)
Packit 032894
  "pfrcpit1\0"
Packit 032894
#define MNE_3DNOW_PFRSQIT1 (MNE_3DNOW_PFRCPIT1 + 9)
Packit 032894
  "pfrsqit1\0"
Packit 032894
#define MNE_3DNOW_PFRCPIT2 (MNE_3DNOW_PFRSQIT1 + 9)
Packit 032894
  "pfrcpit2\0"
Packit 032894
#define MNE_3DNOW_PMULHRW (MNE_3DNOW_PFRCPIT2 + 9)
Packit 032894
  "pmulhrw";
Packit 032894
Packit 032894
#define AMD3DNOW_LOW_IDX 0x0d
Packit 032894
#define AMD3DNOW_HIGH_IDX (sizeof (amd3dnow) + AMD3DNOW_LOW_IDX - 1)
Packit 032894
#define AMD3DNOW_IDX(val) ((val) - AMD3DNOW_LOW_IDX)
Packit 032894
static const unsigned char amd3dnow[] =
Packit 032894
  {
Packit 032894
    [AMD3DNOW_IDX (0xbf)] = MNE_3DNOW_PAVGUSB,
Packit 032894
    [AMD3DNOW_IDX (0x9e)] = MNE_3DNOW_PFADD,
Packit 032894
    [AMD3DNOW_IDX (0x9a)] = MNE_3DNOW_PFSUB,
Packit 032894
    [AMD3DNOW_IDX (0xaa)] = MNE_3DNOW_PFSUBR,
Packit 032894
    [AMD3DNOW_IDX (0xae)] = MNE_3DNOW_PFACC,
Packit 032894
    [AMD3DNOW_IDX (0x90)] = MNE_3DNOW_PFCMPGE,
Packit 032894
    [AMD3DNOW_IDX (0xa0)] = MNE_3DNOW_PFCMPGT,
Packit 032894
    [AMD3DNOW_IDX (0xb0)] = MNE_3DNOW_PFCMPEQ,
Packit 032894
    [AMD3DNOW_IDX (0x94)] = MNE_3DNOW_PFMIN,
Packit 032894
    [AMD3DNOW_IDX (0xa4)] = MNE_3DNOW_PFMAX,
Packit 032894
    [AMD3DNOW_IDX (0x0d)] = MNE_3DNOW_PI2FD,
Packit 032894
    [AMD3DNOW_IDX (0x1d)] = MNE_3DNOW_PF2ID,
Packit 032894
    [AMD3DNOW_IDX (0x96)] = MNE_3DNOW_PFRCP,
Packit 032894
    [AMD3DNOW_IDX (0x97)] = MNE_3DNOW_PFRSQRT,
Packit 032894
    [AMD3DNOW_IDX (0xb4)] = MNE_3DNOW_PFMUL,
Packit 032894
    [AMD3DNOW_IDX (0xa6)] = MNE_3DNOW_PFRCPIT1,
Packit 032894
    [AMD3DNOW_IDX (0xa7)] = MNE_3DNOW_PFRSQIT1,
Packit 032894
    [AMD3DNOW_IDX (0xb6)] = MNE_3DNOW_PFRCPIT2,
Packit 032894
    [AMD3DNOW_IDX (0xb7)] = MNE_3DNOW_PMULHRW
Packit 032894
  };
Packit 032894
Packit 032894
Packit 032894
struct output_data
Packit 032894
{
Packit 032894
  GElf_Addr addr;
Packit 032894
  int *prefixes;
Packit 032894
  size_t opoff1;
Packit 032894
  size_t opoff2;
Packit 032894
  size_t opoff3;
Packit 032894
  char *bufp;
Packit 032894
  size_t *bufcntp;
Packit 032894
  size_t bufsize;
Packit 032894
  const uint8_t *data;
Packit 032894
  const uint8_t **param_start;
Packit 032894
  const uint8_t *end;
Packit 032894
  char *labelbuf;
Packit 032894
  size_t labelbufsize;
Packit 032894
  enum
Packit 032894
    {
Packit 032894
      addr_none = 0,
Packit 032894
      addr_abs_symbolic,
Packit 032894
      addr_abs_always,
Packit 032894
      addr_rel_symbolic,
Packit 032894
      addr_rel_always
Packit 032894
    } symaddr_use;
Packit 032894
  GElf_Addr symaddr;
Packit 032894
};
Packit 032894
Packit 032894
Packit 032894
#ifndef DISFILE
Packit 032894
# define DISFILE "i386_dis.h"
Packit 032894
#endif
Packit 032894
#include DISFILE
Packit 032894
Packit 032894
Packit 032894
#define ADD_CHAR(ch) \
Packit 032894
  do {									      \
Packit 032894
    if (unlikely (bufcnt == bufsize))					      \
Packit 032894
      goto enomem;							      \
Packit 032894
    buf[bufcnt++] = (ch);						      \
Packit 032894
  } while (0)
Packit 032894
Packit 032894
#define ADD_STRING(str) \
Packit 032894
  do {									      \
Packit 032894
    const char *_str0 = (str);						      \
Packit 032894
    size_t _len0 = strlen (_str0);					      \
Packit 032894
    ADD_NSTRING (_str0, _len0);						      \
Packit 032894
  } while (0)
Packit 032894
Packit 032894
#define ADD_NSTRING(str, len) \
Packit 032894
  do {									      \
Packit 032894
    const char *_str = (str);						      \
Packit 032894
    size_t _len = (len);						      \
Packit 032894
    if (unlikely (bufcnt + _len > bufsize))				      \
Packit 032894
      goto enomem;							      \
Packit 032894
    memcpy (buf + bufcnt, _str, _len);					      \
Packit 032894
    bufcnt += _len;							      \
Packit 032894
  } while (0)
Packit 032894
Packit 032894
Packit 032894
int
Packit 032894
i386_disasm (Ebl *ebl __attribute__((unused)),
Packit 032894
	     const uint8_t **startp, const uint8_t *end, GElf_Addr addr,
Packit 032894
	     const char *fmt, DisasmOutputCB_t outcb, DisasmGetSymCB_t symcb,
Packit 032894
	     void *outcbarg, void *symcbarg)
Packit 032894
{
Packit 032894
  const char *save_fmt = fmt;
Packit 032894
Packit 032894
#define BUFSIZE 512
Packit 032894
  char initbuf[BUFSIZE];
Packit 032894
  int prefixes;
Packit 032894
  size_t bufcnt;
Packit 032894
  size_t bufsize = BUFSIZE;
Packit 032894
  char *buf = initbuf;
Packit 032894
  const uint8_t *param_start;
Packit 032894
Packit 032894
  struct output_data output_data =
Packit 032894
    {
Packit 032894
      .prefixes = &prefixes,
Packit 032894
      .bufp = buf,
Packit 032894
      .bufsize = bufsize,
Packit 032894
      .bufcntp = &bufcnt,
Packit 032894
      .param_start = &param_start,
Packit 032894
      .end = end
Packit 032894
    };
Packit 032894
Packit 032894
  int retval = 0;
Packit 032894
  while (1)
Packit 032894
    {
Packit 032894
      prefixes = 0;
Packit 032894
Packit 032894
      const uint8_t *data = *startp;
Packit 032894
      const uint8_t *begin = data;
Packit 032894
Packit 032894
      /* Recognize all prefixes.  */
Packit 032894
      int last_prefix_bit = 0;
Packit 032894
      while (data < end)
Packit 032894
	{
Packit 032894
	  unsigned int i;
Packit 032894
	  for (i = idx_cs; i < nknown_prefixes; ++i)
Packit 032894
	    if (known_prefixes[i] == *data)
Packit 032894
	      break;
Packit 032894
	  if (i == nknown_prefixes)
Packit 032894
	    break;
Packit 032894
Packit 032894
	  prefixes |= last_prefix_bit = 1 << i;
Packit 032894
Packit 032894
	  ++data;
Packit 032894
	}
Packit 032894
Packit 032894
#ifdef X86_64
Packit 032894
      if (data < end && (*data & 0xf0) == 0x40)
Packit 032894
	prefixes |= ((*data++) & 0xf) | has_rex;
Packit 032894
#endif
Packit 032894
Packit 032894
      bufcnt = 0;
Packit 032894
      size_t cnt = 0;
Packit 032894
Packit 032894
      const uint8_t *curr = match_data;
Packit 032894
      const uint8_t *const match_end = match_data + sizeof (match_data);
Packit 032894
Packit 032894
      assert (data <= end);
Packit 032894
      if (data == end)
Packit 032894
	{
Packit 032894
	  if (prefixes != 0)
Packit 032894
	    goto print_prefix;
Packit 032894
Packit 032894
	  retval = -1;
Packit 032894
	  goto do_ret;
Packit 032894
	}
Packit 032894
Packit 032894
    next_match:
Packit 032894
      while (curr < match_end)
Packit 032894
	{
Packit 032894
	  uint_fast8_t len = *curr++;
Packit 032894
	  uint_fast8_t clen = len >> 4;
Packit 032894
	  len &= 0xf;
Packit 032894
	  const uint8_t *next_curr = curr + clen + (len - clen) * 2;
Packit 032894
Packit 032894
	  assert (len > 0);
Packit 032894
	  assert (curr + clen + 2 * (len - clen) <= match_end);
Packit 032894
Packit 032894
	  const uint8_t *codep = data;
Packit 032894
	  int correct_prefix = 0;
Packit 032894
	  int opoff = 0;
Packit 032894
Packit 032894
	  if (data > begin && codep[-1] == *curr && clen > 0)
Packit 032894
	    {
Packit 032894
	      /* We match a prefix byte.  This is exactly one byte and
Packit 032894
		 is matched exactly, without a mask.  */
Packit 032894
	      --len;
Packit 032894
	      --clen;
Packit 032894
	      opoff = 8;
Packit 032894
Packit 032894
	      ++curr;
Packit 032894
Packit Service 35cfd5
	      if (last_prefix_bit == 0)
Packit Service 35cfd5
		goto invalid_op;
Packit 032894
	      correct_prefix = last_prefix_bit;
Packit 032894
	    }
Packit 032894
Packit 032894
	  size_t avail = len;
Packit 032894
	  while (clen > 0)
Packit 032894
	    {
Packit 032894
	      if (*codep++ != *curr++)
Packit 032894
		goto not;
Packit 032894
	      --avail;
Packit 032894
	      --clen;
Packit 032894
	      if (codep == end && avail > 0)
Packit 032894
		goto do_ret;
Packit 032894
	    }
Packit 032894
Packit 032894
	  while (avail > 0)
Packit 032894
	    {
Packit 032894
	      uint_fast8_t masked = *codep++ & *curr++;
Packit 032894
	      if (masked != *curr++)
Packit 032894
		{
Packit 032894
		not:
Packit 032894
		  curr = next_curr;
Packit 032894
		  ++cnt;
Packit 032894
		  bufcnt = 0;
Packit 032894
		  goto next_match;
Packit 032894
		}
Packit 032894
Packit 032894
	      --avail;
Packit 032894
	      if (codep == end && avail > 0)
Packit 032894
		goto do_ret;
Packit 032894
	    }
Packit 032894
Packit 032894
	  if (len > end - data)
Packit 032894
	    /* There is not enough data for the entire instruction.  The
Packit 032894
	       caller can figure this out by looking at the pointer into
Packit 032894
	       the input data.  */
Packit 032894
	    goto do_ret;
Packit 032894
Packit Service 35cfd5
	  if (correct_prefix != 0 && (prefixes & correct_prefix) == 0)
Packit Service 35cfd5
	    goto invalid_op;
Packit 032894
	  prefixes ^= correct_prefix;
Packit 032894
Packit 032894
	  if (0)
Packit 032894
	    {
Packit 032894
	      /* Resize the buffer.  */
Packit 032894
	      char *oldbuf;
Packit 032894
	    enomem:
Packit 032894
	      oldbuf = buf;
Packit 032894
	      if (buf == initbuf)
Packit 032894
		buf = malloc (2 * bufsize);
Packit 032894
	      else
Packit 032894
		buf = realloc (buf, 2 * bufsize);
Packit 032894
	      if (buf == NULL)
Packit 032894
		{
Packit 032894
		  buf = oldbuf;
Packit 032894
		  retval = ENOMEM;
Packit 032894
		  goto do_ret;
Packit 032894
		}
Packit 032894
	      bufsize *= 2;
Packit 032894
Packit 032894
	      output_data.bufp = buf;
Packit 032894
	      output_data.bufsize = bufsize;
Packit 032894
	      bufcnt = 0;
Packit 032894
Packit 032894
	      if (data == end)
Packit 032894
		{
Packit Service 35cfd5
		  if (prefixes == 0)
Packit Service 35cfd5
		    goto invalid_op;
Packit 032894
		  goto print_prefix;
Packit 032894
		}
Packit 032894
Packit 032894
	      /* gcc is not clever enough to see the following variables
Packit 032894
		 are not used uninitialized.  */
Packit 032894
	      asm (""
Packit 032894
		   : "=mr" (opoff), "=mr" (correct_prefix), "=mr" (codep),
Packit 032894
		     "=mr" (next_curr), "=mr" (len));
Packit 032894
	    }
Packit 032894
Packit 032894
	  size_t prefix_size = 0;
Packit 032894
Packit 032894
	  // XXXonly print as prefix if valid?
Packit 032894
	  if ((prefixes & has_lock) != 0)
Packit 032894
	    {
Packit 032894
	      ADD_STRING ("lock ");
Packit 032894
	      prefix_size += 5;
Packit 032894
	    }
Packit 032894
Packit 032894
	  if (instrtab[cnt].rep)
Packit 032894
	    {
Packit 032894
	      if ((prefixes & has_rep) !=  0)
Packit 032894
		{
Packit 032894
		  ADD_STRING ("rep ");
Packit 032894
		  prefix_size += 4;
Packit 032894
		}
Packit 032894
	    }
Packit 032894
	  else if (instrtab[cnt].repe
Packit 032894
		   && (prefixes & (has_rep | has_repne)) != 0)
Packit 032894
	    {
Packit 032894
	      if ((prefixes & has_repne) != 0)
Packit 032894
		{
Packit 032894
		  ADD_STRING ("repne ");
Packit 032894
		  prefix_size += 6;
Packit 032894
		}
Packit 032894
	      else if ((prefixes & has_rep) != 0)
Packit 032894
		{
Packit 032894
		  ADD_STRING ("repe ");
Packit 032894
		  prefix_size += 5;
Packit 032894
		}
Packit 032894
	    }
Packit 032894
	  else if ((prefixes & (has_rep | has_repne)) != 0)
Packit 032894
	    {
Packit 032894
	      uint_fast8_t byte;
Packit 032894
	    print_prefix:
Packit 032894
	      bufcnt = 0;
Packit 032894
	      byte = *begin;
Packit 032894
	      /* This is a prefix byte.  Print it.  */
Packit 032894
	      switch (byte)
Packit 032894
		{
Packit 032894
		case prefix_rep:
Packit 032894
		  ADD_STRING ("rep");
Packit 032894
		  break;
Packit 032894
		case prefix_repne:
Packit 032894
		  ADD_STRING ("repne");
Packit 032894
		  break;
Packit 032894
		case prefix_cs:
Packit 032894
		  ADD_STRING ("cs");
Packit 032894
		  break;
Packit 032894
		case prefix_ds:
Packit 032894
		  ADD_STRING ("ds");
Packit 032894
		  break;
Packit 032894
		case prefix_es:
Packit 032894
		  ADD_STRING ("es");
Packit 032894
		  break;
Packit 032894
		case prefix_fs:
Packit 032894
		  ADD_STRING ("fs");
Packit 032894
		  break;
Packit 032894
		case prefix_gs:
Packit 032894
		  ADD_STRING ("gs");
Packit 032894
		  break;
Packit 032894
		case prefix_ss:
Packit 032894
		  ADD_STRING ("ss");
Packit 032894
		  break;
Packit 032894
		case prefix_data16:
Packit 032894
		  ADD_STRING ("data16");
Packit 032894
		  break;
Packit 032894
		case prefix_addr16:
Packit 032894
		  ADD_STRING ("addr16");
Packit 032894
		  break;
Packit 032894
		case prefix_lock:
Packit 032894
		  ADD_STRING ("lock");
Packit 032894
		  break;
Packit 032894
#ifdef X86_64
Packit 032894
		case 0x40 ... 0x4f:
Packit 032894
		  ADD_STRING ("rex");
Packit 032894
		  if (byte != 0x40)
Packit 032894
		    {
Packit 032894
		      ADD_CHAR ('.');
Packit 032894
		      if (byte & 0x8)
Packit 032894
			ADD_CHAR ('w');
Packit 032894
		      if (byte & 0x4)
Packit 032894
			ADD_CHAR ('r');
Packit 032894
		      if (byte & 0x3)
Packit 032894
			ADD_CHAR ('x');
Packit 032894
		      if (byte & 0x1)
Packit 032894
			ADD_CHAR ('b');
Packit 032894
		    }
Packit 032894
		  break;
Packit 032894
#endif
Packit 032894
		default:
Packit 032894
		  /* Cannot happen.  */
Packit 032894
		  puts ("unknown prefix");
Packit 032894
		  abort ();
Packit 032894
		}
Packit 032894
	      data = begin + 1;
Packit 032894
	      ++addr;
Packit 032894
Packit 032894
	      goto out;
Packit 032894
	    }
Packit 032894
Packit 032894
	  /* We have a match.  First determine how many bytes are
Packit 032894
	     needed for the adressing mode.  */
Packit 032894
	  param_start = codep;
Packit 032894
	  if (instrtab[cnt].modrm)
Packit 032894
	    {
Packit 032894
	      uint_fast8_t modrm = codep[-1];
Packit 032894
Packit 032894
#ifndef X86_64
Packit 032894
	      if (likely ((prefixes & has_addr16) != 0))
Packit 032894
		{
Packit 032894
		  /* Account for displacement.  */
Packit 032894
		  if ((modrm & 0xc7) == 6 || (modrm & 0xc0) == 0x80)
Packit 032894
		    param_start += 2;
Packit 032894
		  else if ((modrm & 0xc0) == 0x40)
Packit 032894
		    param_start += 1;
Packit 032894
		}
Packit 032894
	      else
Packit 032894
#endif
Packit 032894
		{
Packit 032894
		  /* Account for SIB.  */
Packit 032894
		  if ((modrm & 0xc0) != 0xc0 && (modrm & 0x7) == 0x4)
Packit 032894
		    param_start += 1;
Packit 032894
Packit 032894
		  /* Account for displacement.  */
Packit 032894
		  if ((modrm & 0xc7) == 5 || (modrm & 0xc0) == 0x80
Packit 032894
		      || ((modrm & 0xc7) == 0x4
Packit 032894
			  && param_start < end
Packit 032894
			  && (codep[0] & 0x7) == 0x5))
Packit 032894
		    param_start += 4;
Packit 032894
		  else if ((modrm & 0xc0) == 0x40)
Packit 032894
		    param_start += 1;
Packit 032894
		}
Packit 032894
Packit 032894
	      if (unlikely (param_start > end))
Packit 032894
		goto not;
Packit 032894
	    }
Packit 032894
Packit 032894
	  output_data.addr = addr + (data - begin);
Packit 032894
	  output_data.data = data;
Packit 032894
Packit 032894
	  unsigned long string_end_idx = 0;
Packit 032894
	  fmt = save_fmt;
Packit 032894
	  const char *deferred_start = NULL;
Packit 032894
	  size_t deferred_len = 0;
Packit 032894
	  // XXX Can we get this from color.c?
Packit 032894
	  static const char color_off[] = "\e[0m";
Packit 032894
	  while (*fmt != '\0')
Packit 032894
	    {
Packit 032894
	      if (*fmt != '%')
Packit 032894
		{
Packit 032894
		  char ch = *fmt++;
Packit 032894
		  if (ch == '\\')
Packit 032894
		    {
Packit 032894
		      switch ((ch = *fmt++))
Packit 032894
			{
Packit 032894
			case '0' ... '7':
Packit 032894
			  {
Packit 032894
			    int val = ch - '0';
Packit 032894
			    ch = *fmt;
Packit 032894
			    if (ch >= '0' && ch <= '7')
Packit 032894
			      {
Packit 032894
				val *= 8;
Packit 032894
				val += ch - '0';
Packit 032894
				ch = *++fmt;
Packit 032894
				if (ch >= '0' && ch <= '7' && val < 32)
Packit 032894
				  {
Packit 032894
				    val *= 8;
Packit 032894
				    val += ch - '0';
Packit 032894
				    ++fmt;
Packit 032894
				  }
Packit 032894
			      }
Packit 032894
			    ch = val;
Packit 032894
			  }
Packit 032894
			  break;
Packit 032894
Packit 032894
			case 'n':
Packit 032894
			  ch = '\n';
Packit 032894
			  break;
Packit 032894
Packit 032894
			case 't':
Packit 032894
			  ch = '\t';
Packit 032894
			  break;
Packit 032894
Packit 032894
			default:
Packit 032894
			  retval = EINVAL;
Packit 032894
			  goto do_ret;
Packit 032894
			}
Packit 032894
		    }
Packit 032894
		  else if (ch == '\e' && *fmt == '[')
Packit 032894
		    {
Packit 032894
		      deferred_start = fmt - 1;
Packit 032894
		      do
Packit 032894
			++fmt;
Packit 032894
		      while (*fmt != 'm' && *fmt != '\0');
Packit 032894
Packit 032894
		      if (*fmt == 'm')
Packit 032894
			{
Packit 032894
			  deferred_len = ++fmt - deferred_start;
Packit 032894
			  continue;
Packit 032894
			}
Packit 032894
Packit 032894
		      fmt = deferred_start + 1;
Packit 032894
		      deferred_start = NULL;
Packit 032894
		    }
Packit 032894
		  ADD_CHAR (ch);
Packit 032894
		  continue;
Packit 032894
		}
Packit 032894
	      ++fmt;
Packit 032894
Packit 032894
	      int width = 0;
Packit 032894
	      while (isdigit (*fmt))
Packit 032894
		width = width * 10 + (*fmt++ - '0');
Packit 032894
Packit 032894
	      int prec = 0;
Packit 032894
	      if (*fmt == '.')
Packit 032894
		while (isdigit (*++fmt))
Packit 032894
		  prec = prec * 10 + (*fmt - '0');
Packit 032894
Packit 032894
	      size_t start_idx = bufcnt;
Packit 032894
	      size_t non_printing = 0;
Packit 032894
	      switch (*fmt++)
Packit 032894
		{
Packit 032894
		  char mnebuf[16];
Packit 032894
		  const char *str;
Packit 032894
Packit 032894
		case 'm':
Packit 032894
		  /* Mnemonic.  */
Packit 032894
Packit 032894
		  if (unlikely (instrtab[cnt].mnemonic == MNE_INVALID))
Packit 032894
		    {
Packit 032894
		      switch (*data)
Packit 032894
			{
Packit 032894
#ifdef X86_64
Packit 032894
			case 0x90:
Packit 032894
			  if (prefixes & has_rex_b)
Packit 032894
			    goto not;
Packit 032894
			  str = "nop";
Packit 032894
			  break;
Packit 032894
#endif
Packit 032894
Packit 032894
			case 0x98:
Packit 032894
#ifdef X86_64
Packit 032894
			  if (prefixes == (has_rex_w | has_rex))
Packit 032894
			    {
Packit 032894
			      str = "cltq";
Packit 032894
			      break;
Packit 032894
			    }
Packit 032894
#endif
Packit 032894
			  if (prefixes & ~has_data16)
Packit 032894
			    goto print_prefix;
Packit 032894
			  str = prefixes & has_data16 ? "cbtw" : "cwtl";
Packit 032894
			  break;
Packit 032894
Packit 032894
			case 0x99:
Packit 032894
#ifdef X86_64
Packit 032894
			  if (prefixes == (has_rex_w | has_rex))
Packit 032894
			    {
Packit 032894
			      str = "cqto";
Packit 032894
			      break;
Packit 032894
			    }
Packit 032894
#endif
Packit 032894
			  if (prefixes & ~has_data16)
Packit 032894
			    goto print_prefix;
Packit 032894
			  str = prefixes & has_data16 ? "cwtd" : "cltd";
Packit 032894
			  break;
Packit 032894
Packit 032894
			case 0xe3:
Packit 032894
			  if (prefixes & ~has_addr16)
Packit 032894
			    goto print_prefix;
Packit 032894
#ifdef X86_64
Packit 032894
			  str = prefixes & has_addr16 ? "jecxz" : "jrcxz";
Packit 032894
#else
Packit 032894
			  str = prefixes & has_addr16 ? "jcxz" : "jecxz";
Packit 032894
#endif
Packit 032894
			  break;
Packit 032894
Packit 032894
			case 0x0f:
Packit 032894
			  if (data[1] == 0x0f)
Packit 032894
			    {
Packit 032894
			      /* AMD 3DNOW.  We need one more byte.  */
Packit 032894
			      if (param_start >= end)
Packit 032894
				goto not;
Packit 032894
			      if (*param_start < AMD3DNOW_LOW_IDX
Packit 032894
				  || *param_start > AMD3DNOW_HIGH_IDX)
Packit 032894
				goto not;
Packit 032894
			      unsigned int idx
Packit 032894
				= amd3dnow[AMD3DNOW_IDX (*param_start)];
Packit 032894
			      if (idx == 0)
Packit 032894
				goto not;
Packit 032894
			      str = amd3dnowstr + idx - 1;
Packit 032894
			      /* Eat the immediate byte indicating the
Packit 032894
				 operation.  */
Packit 032894
			      ++param_start;
Packit 032894
			      break;
Packit 032894
			    }
Packit 032894
#ifdef X86_64
Packit 032894
			  if (data[1] == 0xc7)
Packit 032894
			    {
Packit 032894
			      str = ((prefixes & has_rex_w)
Packit 032894
				     ? "cmpxchg16b" : "cmpxchg8b");
Packit 032894
			      break;
Packit 032894
			    }
Packit 032894
#endif
Packit 032894
			  if (data[1] == 0xc2)
Packit 032894
			    {
Packit 032894
			      if (param_start >= end)
Packit 032894
				goto not;
Packit 032894
			      if (*param_start > 7)
Packit 032894
				goto not;
Packit 032894
			      static const char cmpops[][9] =
Packit 032894
				{
Packit 032894
				  [0] = "cmpeq",
Packit 032894
				  [1] = "cmplt",
Packit 032894
				  [2] = "cmple",
Packit 032894
				  [3] = "cmpunord",
Packit 032894
				  [4] = "cmpneq",
Packit 032894
				  [5] = "cmpnlt",
Packit 032894
				  [6] = "cmpnle",
Packit 032894
				  [7] = "cmpord"
Packit 032894
				};
Packit 032894
			      char *cp = stpcpy (mnebuf, cmpops[*param_start]);
Packit 032894
			      if (correct_prefix & (has_rep | has_repne))
Packit 032894
				*cp++ = 's';
Packit 032894
			      else
Packit 032894
				*cp++ = 'p';
Packit 032894
			      if (correct_prefix & (has_data16 | has_repne))
Packit 032894
				*cp++ = 'd';
Packit 032894
			      else
Packit 032894
				*cp++ = 's';
Packit 032894
			      *cp = '\0';
Packit 032894
			      str = mnebuf;
Packit 032894
			      /* Eat the immediate byte indicating the
Packit 032894
				 operation.  */
Packit 032894
			      ++param_start;
Packit 032894
			      break;
Packit 032894
			    }
Packit 032894
			  FALLTHROUGH;
Packit 032894
			default:
Packit 032894
			  str = "INVALID not handled";
Packit 032894
			  break;
Packit 032894
			}
Packit 032894
		    }
Packit 032894
		  else
Packit 032894
		    str = mnestr.str + mneidx[instrtab[cnt].mnemonic];
Packit 032894
Packit 032894
		  if (deferred_start != NULL)
Packit 032894
		    {
Packit 032894
		      ADD_NSTRING (deferred_start, deferred_len);
Packit 032894
		      non_printing += deferred_len;
Packit 032894
		    }
Packit 032894
Packit 032894
		  ADD_STRING (str);
Packit 032894
Packit 032894
		  switch (instrtab[cnt].suffix)
Packit 032894
		    {
Packit 032894
		    case suffix_none:
Packit 032894
		      break;
Packit 032894
Packit 032894
		    case suffix_w:
Packit 032894
		      if ((codep[-1] & 0xc0) != 0xc0)
Packit 032894
			{
Packit 032894
			  char ch;
Packit 032894
Packit 032894
			  if (data[0] & 1)
Packit 032894
			    {
Packit 032894
			      if (prefixes & has_data16)
Packit 032894
				ch = 'w';
Packit 032894
#ifdef X86_64
Packit 032894
			      else if (prefixes & has_rex_w)
Packit 032894
				ch = 'q';
Packit 032894
#endif
Packit 032894
			      else
Packit 032894
				ch = 'l';
Packit 032894
			    }
Packit 032894
			  else
Packit 032894
			    ch = 'b';
Packit 032894
Packit 032894
			  ADD_CHAR (ch);
Packit 032894
			}
Packit 032894
		      break;
Packit 032894
Packit 032894
		    case suffix_w0:
Packit 032894
		      if ((codep[-1] & 0xc0) != 0xc0)
Packit 032894
			ADD_CHAR ('l');
Packit 032894
		      break;
Packit 032894
Packit 032894
		    case suffix_w1:
Packit 032894
		      if ((data[0] & 0x4) == 0)
Packit 032894
			ADD_CHAR ('l');
Packit 032894
		      break;
Packit 032894
Packit 032894
		    case suffix_W:
Packit 032894
		      if (prefixes & has_data16)
Packit 032894
			{
Packit 032894
			  ADD_CHAR ('w');
Packit 032894
			  prefixes &= ~has_data16;
Packit 032894
			}
Packit 032894
#ifdef X86_64
Packit 032894
		      else
Packit 032894
			ADD_CHAR ('q');
Packit 032894
#endif
Packit 032894
		      break;
Packit 032894
Packit 032894
		    case suffix_W1:
Packit 032894
		      if (prefixes & has_data16)
Packit 032894
			{
Packit 032894
			  ADD_CHAR ('w');
Packit 032894
			  prefixes &= ~has_data16;
Packit 032894
			}
Packit 032894
#ifdef X86_64
Packit 032894
		      else if (prefixes & has_rex_w)
Packit 032894
			ADD_CHAR ('q');
Packit 032894
#endif
Packit 032894
		      break;
Packit 032894
Packit 032894
		    case suffix_tttn:;
Packit 032894
		      static const char tttn[16][3] =
Packit 032894
			{
Packit 032894
			  "o", "no", "b", "ae", "e", "ne", "be", "a",
Packit 032894
			  "s", "ns", "p", "np", "l", "ge", "le", "g"
Packit 032894
			};
Packit 032894
		      ADD_STRING (tttn[codep[-1 - instrtab[cnt].modrm] & 0x0f]);
Packit 032894
		      break;
Packit 032894
Packit 032894
		    case suffix_D:
Packit 032894
		      if ((codep[-1] & 0xc0) != 0xc0)
Packit 032894
			ADD_CHAR ((data[0] & 0x04) == 0 ? 's' : 'l');
Packit 032894
		      break;
Packit 032894
Packit 032894
		    default:
Packit 032894
		      printf("unknown suffix %d\n", instrtab[cnt].suffix);
Packit 032894
		      abort ();
Packit 032894
		    }
Packit 032894
Packit 032894
		  if (deferred_start != NULL)
Packit 032894
		    {
Packit 032894
		      ADD_STRING (color_off);
Packit 032894
		      non_printing += strlen (color_off);
Packit 032894
		    }
Packit 032894
Packit 032894
		  string_end_idx = bufcnt;
Packit 032894
		  break;
Packit 032894
Packit 032894
		case 'o':
Packit 032894
		  if (prec == 1 && instrtab[cnt].fct1 != 0)
Packit 032894
		    {
Packit 032894
		      /* First parameter.  */
Packit 032894
		      if (deferred_start != NULL)
Packit 032894
			{
Packit 032894
			  ADD_NSTRING (deferred_start, deferred_len);
Packit 032894
			  non_printing += deferred_len;
Packit 032894
			}
Packit 032894
Packit 032894
		      if (instrtab[cnt].str1 != 0)
Packit 032894
			ADD_STRING (op1_str
Packit 032894
				    + op1_str_idx[instrtab[cnt].str1 - 1]);
Packit 032894
Packit 032894
		      output_data.opoff1 = (instrtab[cnt].off1_1
Packit 032894
					    + OFF1_1_BIAS - opoff);
Packit 032894
		      output_data.opoff2 = (instrtab[cnt].off1_2
Packit 032894
					    + OFF1_2_BIAS - opoff);
Packit 032894
		      output_data.opoff3 = (instrtab[cnt].off1_3
Packit 032894
					    + OFF1_3_BIAS - opoff);
Packit 032894
		      int r = op1_fct[instrtab[cnt].fct1] (&output_data);
Packit 032894
		      if (r < 0)
Packit 032894
			goto not;
Packit 032894
		      if (r > 0)
Packit 032894
			goto enomem;
Packit 032894
Packit 032894
		      if (deferred_start != NULL)
Packit 032894
			{
Packit 032894
			  ADD_STRING (color_off);
Packit 032894
			  non_printing += strlen (color_off);
Packit 032894
			}
Packit 032894
Packit 032894
		      string_end_idx = bufcnt;
Packit 032894
		    }
Packit 032894
		  else if (prec == 2 && instrtab[cnt].fct2 != 0)
Packit 032894
		    {
Packit 032894
		      /* Second parameter.  */
Packit 032894
		      if (deferred_start != NULL)
Packit 032894
			{
Packit 032894
			  ADD_NSTRING (deferred_start, deferred_len);
Packit 032894
			  non_printing += deferred_len;
Packit 032894
			}
Packit 032894
Packit 032894
		      if (instrtab[cnt].str2 != 0)
Packit 032894
			ADD_STRING (op2_str
Packit 032894
				    + op2_str_idx[instrtab[cnt].str2 - 1]);
Packit 032894
Packit 032894
		      output_data.opoff1 = (instrtab[cnt].off2_1
Packit 032894
					    + OFF2_1_BIAS - opoff);
Packit 032894
		      output_data.opoff2 = (instrtab[cnt].off2_2
Packit 032894
					    + OFF2_2_BIAS - opoff);
Packit 032894
		      output_data.opoff3 = (instrtab[cnt].off2_3
Packit 032894
					    + OFF2_3_BIAS - opoff);
Packit 032894
		      int r = op2_fct[instrtab[cnt].fct2] (&output_data);
Packit 032894
		      if (r < 0)
Packit 032894
			goto not;
Packit 032894
		      if (r > 0)
Packit 032894
			goto enomem;
Packit 032894
Packit 032894
		      if (deferred_start != NULL)
Packit 032894
			{
Packit 032894
			  ADD_STRING (color_off);
Packit 032894
			  non_printing += strlen (color_off);
Packit 032894
			}
Packit 032894
Packit 032894
		      string_end_idx = bufcnt;
Packit 032894
		    }
Packit 032894
		  else if (prec == 3 && instrtab[cnt].fct3 != 0)
Packit 032894
		    {
Packit 032894
		      /* Third parameter.  */
Packit 032894
		      if (deferred_start != NULL)
Packit 032894
			{
Packit 032894
			  ADD_NSTRING (deferred_start, deferred_len);
Packit 032894
			  non_printing += deferred_len;
Packit 032894
			}
Packit 032894
Packit 032894
		      if (instrtab[cnt].str3 != 0)
Packit 032894
			ADD_STRING (op3_str
Packit 032894
				    + op3_str_idx[instrtab[cnt].str3 - 1]);
Packit 032894
Packit 032894
		      output_data.opoff1 = (instrtab[cnt].off3_1
Packit 032894
					    + OFF3_1_BIAS - opoff);
Packit 032894
		      output_data.opoff2 = (instrtab[cnt].off3_2
Packit 032894
					    + OFF3_2_BIAS - opoff);
Packit 032894
#ifdef OFF3_3_BITS
Packit 032894
		      output_data.opoff3 = (instrtab[cnt].off3_3
Packit 032894
					    + OFF3_3_BIAS - opoff);
Packit 032894
#else
Packit 032894
		      output_data.opoff3 = 0;
Packit 032894
#endif
Packit 032894
		      int r = op3_fct[instrtab[cnt].fct3] (&output_data);
Packit 032894
		      if (r < 0)
Packit 032894
			goto not;
Packit 032894
		      if (r > 0)
Packit 032894
			goto enomem;
Packit 032894
Packit 032894
		      if (deferred_start != NULL)
Packit 032894
			{
Packit 032894
			  ADD_STRING (color_off);
Packit 032894
			  non_printing += strlen (color_off);
Packit 032894
			}
Packit 032894
Packit 032894
		      string_end_idx = bufcnt;
Packit 032894
		    }
Packit 032894
		  else
Packit 032894
		    start_idx = bufcnt = string_end_idx;
Packit 032894
		  break;
Packit 032894
Packit 032894
		case 'e':
Packit 032894
		  string_end_idx = bufcnt;
Packit 032894
		  break;
Packit 032894
Packit 032894
		case 'a':
Packit 032894
		  /* Pad to requested column.  */
Packit 032894
		  while (bufcnt - non_printing < (size_t) width)
Packit 032894
		    ADD_CHAR (' ');
Packit 032894
		  width = 0;
Packit 032894
		  break;
Packit 032894
Packit 032894
		case 'l':
Packit 032894
		  if (deferred_start != NULL)
Packit 032894
		    {
Packit 032894
		      ADD_NSTRING (deferred_start, deferred_len);
Packit 032894
		      non_printing += deferred_len;
Packit 032894
		    }
Packit 032894
Packit 032894
		  if (output_data.labelbuf != NULL
Packit 032894
		      && output_data.labelbuf[0] != '\0')
Packit 032894
		    {
Packit 032894
		      ADD_STRING (output_data.labelbuf);
Packit 032894
		      output_data.labelbuf[0] = '\0';
Packit 032894
		      string_end_idx = bufcnt;
Packit 032894
		    }
Packit 032894
		  else if (output_data.symaddr_use != addr_none)
Packit 032894
		    {
Packit 032894
		      GElf_Addr symaddr = output_data.symaddr;
Packit 032894
		      if (output_data.symaddr_use >= addr_rel_symbolic)
Packit 032894
			symaddr += addr + param_start - begin;
Packit 032894
Packit 032894
		      // XXX Lookup symbol based on symaddr
Packit 032894
		      const char *symstr = NULL;
Packit 032894
		      if (symcb != NULL
Packit 032894
			  && symcb (0 /* XXX */, 0 /* XXX */, symaddr,
Packit 032894
				    &output_data.labelbuf,
Packit 032894
				    &output_data.labelbufsize, symcbarg) == 0)
Packit 032894
			symstr = output_data.labelbuf;
Packit 032894
Packit 032894
		      size_t bufavail = bufsize - bufcnt;
Packit 032894
		      int r = 0;
Packit 032894
		      if (symstr != NULL)
Packit 032894
			r = snprintf (&buf[bufcnt], bufavail, "# <%s>",
Packit 032894
				      symstr);
Packit 032894
		      else if (output_data.symaddr_use == addr_abs_always
Packit 032894
			       || output_data.symaddr_use == addr_rel_always)
Packit 032894
			r = snprintf (&buf[bufcnt], bufavail, "# %#" PRIx64,
Packit 032894
				      (uint64_t) symaddr);
Packit 032894
Packit 032894
		      assert (r >= 0);
Packit 032894
		      if ((size_t) r >= bufavail)
Packit 032894
			goto enomem;
Packit 032894
		      bufcnt += r;
Packit 032894
		      string_end_idx = bufcnt;
Packit 032894
Packit 032894
		      output_data.symaddr_use = addr_none;
Packit 032894
		    }
Packit 032894
		  if (deferred_start != NULL)
Packit 032894
		    {
Packit 032894
		      ADD_STRING (color_off);
Packit 032894
		      non_printing += strlen (color_off);
Packit 032894
		    }
Packit 032894
		  break;
Packit 032894
Packit 032894
		default:
Packit 032894
		  abort ();
Packit 032894
		}
Packit 032894
Packit 032894
	      deferred_start = NULL;
Packit 032894
Packit 032894
	      /* Pad according to the specified width.  */
Packit 032894
	      while (bufcnt + prefix_size - non_printing < start_idx + width)
Packit 032894
		ADD_CHAR (' ');
Packit 032894
	      prefix_size = 0;
Packit 032894
	    }
Packit 032894
Packit 032894
	  if ((prefixes & SEGMENT_PREFIXES) != 0)
Packit 032894
	    goto print_prefix;
Packit 032894
Packit 032894
	  assert (string_end_idx != ~0ul);
Packit 032894
	  bufcnt = string_end_idx;
Packit 032894
Packit 032894
	  addr += param_start - begin;
Packit 032894
	  data = param_start;
Packit 032894
Packit 032894
	  goto out;
Packit 032894
	}
Packit 032894
Packit 032894
      /* Invalid (or at least unhandled) opcode.  */
Packit Service 35cfd5
    invalid_op:
Packit 032894
      if (prefixes != 0)
Packit 032894
	goto print_prefix;
Packit 032894
      /* Make sure we get past the unrecognized opcode if we haven't yet.  */
Packit 032894
      if (*startp == data)
Packit 032894
	++data;
Packit 032894
      ADD_STRING ("(bad)");
Packit 032894
      addr += data - begin;
Packit 032894
Packit 032894
    out:
Packit 032894
      if (bufcnt == bufsize)
Packit 032894
	goto enomem;
Packit 032894
      buf[bufcnt] = '\0';
Packit 032894
Packit 032894
      *startp = data;
Packit 032894
      retval = outcb (buf, bufcnt, outcbarg);
Packit 032894
      if (retval != 0)
Packit 032894
	goto do_ret;
Packit 032894
    }
Packit 032894
Packit 032894
 do_ret:
Packit 032894
  free (output_data.labelbuf);
Packit 032894
  if (buf != initbuf)
Packit 032894
    free (buf);
Packit 032894
Packit 032894
  return retval;
Packit 032894
}