Rizin
unix-like reverse engineering framework and cli tools
xtensa-dis.c
Go to the documentation of this file.
1 /* xtensa-dis.c. Disassembly functions for Xtensa.
2  Copyright (C) 2003-2015 Free Software Foundation, Inc.
3  Contributed by Bob Wilson at Tensilica, Inc. (bwilson@tensilica.com)
4 
5  This file is part of the GNU opcodes library.
6 
7  This library is free software; you can redistribute it and/or modify
8  it under the terms of the GNU General Public License as published by
9  the Free Software Foundation; either version 3, or (at your option)
10  any later version.
11 
12  It is distributed in the hope that it will be useful, but WITHOUT
13  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14  or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
15  License for more details.
16 
17  You should have received a copy of the GNU General Public License
18  along with this file; see the file COPYING. If not, write to the
19  Free Software Foundation, 51 Franklin Street - Fifth Floor, Boston,
20  MA 02110-1301, USA. */
21 
22 #include "sysdep.h"
23 #include <stdlib.h>
24 #include <stdio.h>
25 #include <sys/types.h>
26 #include <string.h>
27 #include "xtensa-isa.h"
28 #include "ansidecl.h"
29 #include <setjmp.h>
30 #include "disas-asm.h"
31 #include "libiberty.h"
32 
33 
34 #if defined(_MSC_VER)
35 __declspec(dllimport)
36 #endif
38 
39 #ifndef MAX
40 #define MAX(a,b) (((a)) > ((b)) ? ((a)) : ((b)))
41 #endif
42 
43 #if 1
44 static void nothing(void) {
45  return;
46 }
47 
48 #define OPCODES_SIGJMP_BUF void*
49 #define OPCODES_SIGSETJMP(buf) nothing()
50 #define OPCODES_SIGLONGJMP(buf,val) nothing()
51 #else
52 
53 #define OPCODES_SIGJMP_BUF sigjmp_buf
54 #define OPCODES_SIGSETJMP(buf) sigsetjmp((buf), 0)
55 #define OPCODES_SIGLONGJMP(buf,val) siglongjmp((buf), (val))
56 #endif
57 
59 
61 {
64 };
65 
66 
67 static int
69 {
70  int length, status = 0;
71  struct dis_private *priv = (struct dis_private *) info->private_data;
72  int insn_size = xtensa_isa_maxlength (xtensa_default_isa);
73 
74  /* Read the maximum instruction size, padding with zeros if we go past
75  the end of the text section. This code will automatically adjust
76  length when we hit the end of the buffer. */
77 
78  memset (priv->byte_buf, 0, insn_size);
79  for (length = insn_size; length > 0; length--)
80  {
81  status = (*info->read_memory_func) (memaddr, priv->byte_buf, length,
82  info);
83  if (status == 0) {
84  return length;
85  }
86  }
87  (*info->memory_error_func) (status, memaddr, info);
88  OPCODES_SIGLONGJMP (priv->bailout, 1);
89 return -1;
90  /*NOTREACHED*/
91 }
92 
93 
94 static void
96  struct disassemble_info *info,
98  int opnd,
99  unsigned operand_val)
100 {
102  int signed_operand_val;
103 
104  if (show_raw_fields)
105  {
106  if (operand_val < 0xa) {
107  (*info->fprintf_func) (info->stream, "%u", operand_val);
108  } else {
109  (*info->fprintf_func) (info->stream, "0x%x", operand_val);
110  }
111  return;
112  }
113 
114  (void) xtensa_operand_decode (isa, opc, opnd, &operand_val);
115  signed_operand_val = (int) operand_val;
116 
117  if (xtensa_operand_is_register (isa, opc, opnd) == 0)
118  {
119  if (xtensa_operand_is_PCrelative (isa, opc, opnd) == 1)
120  {
121  (void) xtensa_operand_undo_reloc (isa, opc, opnd,
122  &operand_val, memaddr);
123  info->target = operand_val;
124  (*info->print_address_func) (info->target, info);
125  }
126  else
127  {
128  if ((signed_operand_val > -256) && (signed_operand_val < 256)) {
129  (*info->fprintf_func) (info->stream, "%d", signed_operand_val);
130  } else {
131  (*info->fprintf_func) (info->stream, "0x%x", signed_operand_val);
132  }
133  }
134  }
135  else
136  {
137  int i = 1;
138  xtensa_regfile opnd_rf = xtensa_operand_regfile (isa, opc, opnd);
139  (*info->fprintf_func) (info->stream, "%s%u",
140  xtensa_regfile_shortname (isa, opnd_rf),
141  operand_val);
142  while (i < xtensa_operand_num_regs (isa, opc, opnd))
143  {
144  operand_val++;
145  (*info->fprintf_func) (info->stream, ":%s%u",
146  xtensa_regfile_shortname (isa, opnd_rf),
147  operand_val);
148  i++;
149  }
150  }
151 }
152 
153 
154 /* Print the Xtensa instruction at address MEMADDR on info->stream.
155  Returns length of the instruction in bytes. */
156 
157 int
159 {
160  unsigned operand_val;
161  int bytes_fetched, size, maxsize, i, n, noperands, nslots;
162  xtensa_isa isa;
164  xtensa_format fmt;
165  struct dis_private priv;
166  static bfd_byte *byte_buf = NULL;
167  static xtensa_insnbuf insn_buffer = NULL;
168  static xtensa_insnbuf slot_buffer = NULL;
169  int first, first_slot, valid_insn;
170 
171  if (!xtensa_default_isa) {
173  }
174 
175  info->target = 0;
177 
178  /* Set bytes_per_line to control the amount of whitespace between the hex
179  values and the opcode. For Xtensa, we always print one "chunk" and we
180  vary bytes_per_chunk to determine how many bytes to print. (objdump
181  would apparently prefer that we set bytes_per_chunk to 1 and vary
182  bytes_per_line but that makes it hard to fit 64-bit instructions on
183  an 80-column screen.) The value of bytes_per_line here is not exactly
184  right, because objdump adds an extra space for each chunk so that the
185  amount of whitespace depends on the chunk size. Oh well, it's good
186  enough.... Note that we set the minimum size to 4 to accommodate
187  literal pools. */
188  info->bytes_per_line = MAX (maxsize, 4);
189 
190  /* Allocate buffers the first time through. */
191  if (!insn_buffer)
192  {
195  byte_buf = (bfd_byte *) xmalloc (MAX (maxsize, 4));
196  }
197 
198  priv.byte_buf = byte_buf;
199 
200  info->private_data = (void *) &priv;
201 #if 0
202  if (OPCODES_SIGSETJMP (priv.bailout) != 0)
203  /* Error return. */
204  return -1;
205 #endif
206 
207  /* Don't set "isa" before the setjmp to keep the compiler from griping. */
208  isa = xtensa_default_isa;
209  size = 0;
210  nslots = 0;
211 
212  /* Fetch the maximum size instruction. */
213  bytes_fetched = fetch_data (info, memaddr);
214 
215  /* Copy the bytes into the decode buffer. */
216  memset (insn_buffer, 0, (xtensa_insnbuf_size (isa) *
217  sizeof (xtensa_insnbuf_word)));
218  xtensa_insnbuf_from_chars (isa, insn_buffer, priv.byte_buf, bytes_fetched);
219 
220  fmt = xtensa_format_decode (isa, insn_buffer);
221  if (fmt == XTENSA_UNDEFINED || ((size = xtensa_format_length (isa, fmt)) > bytes_fetched)) {
222  valid_insn = 0;
223  } else {
224  /* Make sure all the opcodes are valid. */
225  valid_insn = 1;
226  nslots = xtensa_format_num_slots (isa, fmt);
227  for (n = 0; n < nslots; n++) {
228  xtensa_format_get_slot (isa, fmt, n, insn_buffer, slot_buffer);
229  if (xtensa_opcode_decode (isa, fmt, n, slot_buffer) == XTENSA_UNDEFINED) {
230  valid_insn = 0;
231  break;
232  }
233  }
234  }
235 
236  if (!valid_insn)
237  {
238  (*info->fprintf_func) (info->stream, ".byte %#02x", priv.byte_buf[0]);
239  return 1;
240  }
241 
242  if (nslots > 1) {
243  (*info->fprintf_func) (info->stream, "{ ");
244  }
245 
246  first_slot = 1;
247  for (n = 0; n < nslots; n++) {
248  if (first_slot) {
249  first_slot = 0;
250  } else {
251  (*info->fprintf_func) (info->stream, "; ");
252  }
253 
254  xtensa_format_get_slot (isa, fmt, n, insn_buffer, slot_buffer);
255  opc = xtensa_opcode_decode (isa, fmt, n, slot_buffer);
256  (*info->fprintf_func) (info->stream, "%s",
257  xtensa_opcode_name (isa, opc));
258 
259  /* Print the operands (if any). */
260  noperands = xtensa_opcode_num_operands (isa, opc);
261  first = 1;
262  for (i = 0; i < noperands; i++) {
263  if (xtensa_operand_is_visible (isa, opc, i) == 0) {
264  continue;
265  }
266  if (first) {
267  (*info->fprintf_func) (info->stream, " ");
268  first = 0;
269  } else {
270  (*info->fprintf_func) (info->stream, ", ");
271  }
272  (void)xtensa_operand_get_field (isa, opc, i, fmt, n,
273  slot_buffer, &operand_val);
274 
275  print_xtensa_operand (memaddr, info, opc, i, operand_val);
276  }
277  }
278 
279  if (nslots > 1) {
280  (*info->fprintf_func) (info->stream, " }");
281  }
282 
283  info->bytes_per_chunk = size;
284  info->display_endian = info->endian;
285 
286  return size;
287 }
288 
lzma_index ** i
Definition: index.h:629
RzBinInfo * info(RzBinFile *bf)
Definition: bin_ne.c:86
#define NULL
Definition: cris-opc.c:27
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz static mask static vfork const void static prot static getpgrp const char static swapflags static arg static fd static protocol static who struct sockaddr static addrlen static backlog struct timeval struct timezone static tz const struct iovec static count static mode const void const struct sockaddr static tolen const char static pathname void static offset struct stat static buf void long static basep static whence static length const void static len static semflg const void static shmflg const struct timespec struct timespec static rem const char static group const void length
Definition: sflib.h:133
static ut64 opc
Definition: desil.c:33
#define xmalloc
Definition: disas-asm.h:43
voidpf void uLong size
Definition: ioapi.h:138
return memset(p, 0, total)
static const char struct stat static buf struct stat static buf static vhangup int status
Definition: sflib.h:145
int n
Definition: mipsasm.c:19
unsigned char bfd_byte
Definition: mybfd.h:176
BFD_HOST_U_64_BIT bfd_vma
Definition: mybfd.h:111
static int
Definition: sfsocketcall.h:114
bfd_byte * byte_buf
Definition: xtensa-dis.c:62
OPCODES_SIGJMP_BUF bailout
Definition: xtensa-dis.c:63
__declspec(noreturn) void uv_fatal_error(const int errorno
static void print_xtensa_operand(bfd_vma memaddr, struct disassemble_info *info, xtensa_opcode opc, int opnd, unsigned operand_val)
Definition: xtensa-dis.c:95
static void nothing(void)
Definition: xtensa-dis.c:44
int print_insn_xtensa(bfd_vma memaddr, struct disassemble_info *info)
Definition: xtensa-dis.c:158
static int fetch_data(struct disassemble_info *info, bfd_vma memaddr)
Definition: xtensa-dis.c:68
#define OPCODES_SIGSETJMP(buf)
Definition: xtensa-dis.c:49
#define OPCODES_SIGJMP_BUF
Definition: xtensa-dis.c:48
#define OPCODES_SIGLONGJMP(buf, val)
Definition: xtensa-dis.c:50
xtensa_isa xtensa_default_isa
Definition: elf32-xtensa.c:147
int show_raw_fields
Definition: xtensa-dis.c:58
#define MAX(a, b)
Definition: xtensa-dis.c:40
const char * xtensa_regfile_shortname(xtensa_isa isa, xtensa_regfile rf)
Definition: xtensa-isa.c:1474
int xtensa_operand_is_PCrelative(xtensa_isa isa, xtensa_opcode opc, int opnd)
Definition: xtensa-isa.c:1221
int xtensa_format_get_slot(xtensa_isa isa, xtensa_format fmt, int slot, const xtensa_insnbuf insn, xtensa_insnbuf slotbuf)
Definition: xtensa-isa.c:629
int xtensa_opcode
Definition: xtensa-isa.h:83
int xtensa_format
Definition: xtensa-isa.h:84
int xtensa_format_num_slots(xtensa_isa isa, xtensa_format fmt)
Definition: xtensa-isa.c:606
int xtensa_operand_undo_reloc(xtensa_isa isa, xtensa_opcode opc, int opnd, uint32 *valp, uint32 pc)
Definition: xtensa-isa.c:1274
int xtensa_operand_num_regs(xtensa_isa isa, xtensa_opcode opc, int opnd)
Definition: xtensa-isa.c:1188
int xtensa_operand_is_register(xtensa_isa isa, xtensa_opcode opc, int opnd)
Definition: xtensa-isa.c:1155
uint32 xtensa_insnbuf_word
Definition: xtensa-isa.h:178
int xtensa_regfile
Definition: xtensa-isa.h:85
xtensa_opcode xtensa_opcode_decode(xtensa_isa isa, xtensa_format fmt, int slot, const xtensa_insnbuf slotbuf)
Definition: xtensa-isa.c:708
int xtensa_opcode_num_operands(xtensa_isa isa, xtensa_opcode opc)
Definition: xtensa-isa.c:816
xtensa_insnbuf_word * xtensa_insnbuf
Definition: xtensa-isa.h:179
int xtensa_insnbuf_size(xtensa_isa isa)
Definition: xtensa-isa.c:80
xtensa_regfile xtensa_operand_regfile(xtensa_isa isa, xtensa_opcode opc, int opnd)
Definition: xtensa-isa.c:1173
int xtensa_operand_get_field(xtensa_isa isa, xtensa_opcode opc, int opnd, xtensa_format fmt, int slot, const xtensa_insnbuf slotbuf, uint32 *valp)
Definition: xtensa-isa.c:975
int xtensa_operand_decode(xtensa_isa isa, xtensa_opcode opc, int opnd, uint32 *valp)
Definition: xtensa-isa.c:1128
int xtensa_format_length(xtensa_isa isa, xtensa_format fmt)
Definition: xtensa-isa.c:597
#define XTENSA_UNDEFINED
Definition: xtensa-isa.h:93
xtensa_format xtensa_format_decode(xtensa_isa isa, const xtensa_insnbuf insn)
Definition: xtensa-isa.c:570
void xtensa_insnbuf_from_chars(xtensa_isa isa, xtensa_insnbuf insn, const unsigned char *cp, int num_chars)
Definition: xtensa-isa.c:196
xtensa_isa xtensa_isa_init(xtensa_isa_status *errno_p, char **error_msg_p)
Definition: xtensa-isa.c:248
int xtensa_operand_is_visible(xtensa_isa isa, xtensa_opcode opc, int opnd)
Definition: xtensa-isa.c:924
int xtensa_isa_maxlength(xtensa_isa isa)
Definition: xtensa-isa.c:405
const char * xtensa_opcode_name(xtensa_isa isa, xtensa_opcode opc)
Definition: xtensa-isa.c:759
xtensa_insnbuf xtensa_insnbuf_alloc(xtensa_isa isa)
Definition: xtensa-isa.c:88