Fix all failing FPXX tests for tx39-elf.
[platform/upstream/binutils.git] / gdb / guile / scm-disasm.c
1 /* Scheme interface to architecture.
2
3    Copyright (C) 2014 Free Software Foundation, Inc.
4
5    This file is part of GDB.
6
7    This program 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 of the License, or
10    (at your option) any later version.
11
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
19
20 /* See README file in this directory for implementation notes, coding
21    conventions, et.al.  */
22
23 #include "defs.h"
24 #include "arch-utils.h"
25 #include "disasm.h"
26 #include "dis-asm.h"
27 #include "gdbarch.h"
28 #include "gdbcore.h" /* Why is memory_error here? */
29 #include "guile-internal.h"
30
31 static SCM port_keyword;
32 static SCM offset_keyword;
33 static SCM size_keyword;
34 static SCM count_keyword;
35
36 static SCM address_symbol;
37 static SCM asm_symbol;
38 static SCM length_symbol;
39
40 /* Struct used to pass "application data" in disassemble_info.  */
41
42 struct gdbscm_disasm_data
43 {
44   struct gdbarch *gdbarch;
45   SCM port;
46   /* The offset of the address of the first instruction in PORT.  */
47   ULONGEST offset;
48 };
49
50 /* Struct used to pass data from gdbscm_disasm_read_memory to
51    gdbscm_disasm_read_memory_worker.  */
52
53 struct gdbscm_disasm_read_data
54 {
55   bfd_vma memaddr;
56   bfd_byte *myaddr;
57   unsigned int length;
58   struct disassemble_info *dinfo;
59 };
60 \f
61 /* Subroutine of gdbscm_arch_disassemble to simplify it.
62    Return the result for one instruction.  */
63
64 static SCM
65 dascm_make_insn (CORE_ADDR pc, const char *assembly, int insn_len)
66 {
67   return scm_list_3 (scm_cons (address_symbol,
68                                gdbscm_scm_from_ulongest (pc)),
69                      scm_cons (asm_symbol,
70                                gdbscm_scm_from_c_string (assembly)),
71                      scm_cons (length_symbol,
72                                scm_from_int (insn_len)));
73 }
74
75 /* Helper function for gdbscm_disasm_read_memory to safely read from a
76    Scheme port.  Called via gdbscm_call_guile.
77    The result is a statically allocated error message or NULL if success.  */
78
79 static void *
80 gdbscm_disasm_read_memory_worker (void *datap)
81 {
82   struct gdbscm_disasm_read_data *data = datap;
83   struct disassemble_info *dinfo = data->dinfo;
84   struct gdbscm_disasm_data *disasm_data = dinfo->application_data;
85   SCM seekto, newpos, port = disasm_data->port;
86   size_t bytes_read;
87
88   seekto = gdbscm_scm_from_ulongest (data->memaddr - disasm_data->offset);
89   newpos = scm_seek (port, seekto, scm_from_int (SEEK_SET));
90   if (!scm_is_eq (seekto, newpos))
91     return "seek error";
92
93   bytes_read = scm_c_read (port, data->myaddr, data->length);
94
95   if (bytes_read != data->length)
96     return "short read";
97
98   /* If we get here the read succeeded.  */
99   return NULL;
100 }
101
102 /* disassemble_info.read_memory_func for gdbscm_print_insn_from_port.  */
103
104 static int
105 gdbscm_disasm_read_memory (bfd_vma memaddr, bfd_byte *myaddr,
106                            unsigned int length,
107                            struct disassemble_info *dinfo)
108 {
109   struct gdbscm_disasm_read_data data;
110   void *status;
111
112   data.memaddr = memaddr;
113   data.myaddr = myaddr;
114   data.length = length;
115   data.dinfo = dinfo;
116
117   status = gdbscm_with_guile (gdbscm_disasm_read_memory_worker, &data);
118
119   /* TODO: IWBN to distinguish problems reading target memory versus problems
120      with the port (e.g., EOF).
121      We return TARGET_XFER_E_IO here as that's what memory_error looks for.  */
122   return status != NULL ? TARGET_XFER_E_IO : 0;
123 }
124
125 /* disassemble_info.memory_error_func for gdbscm_print_insn_from_port.
126    Technically speaking, we don't need our own memory_error_func,
127    but to not provide one would leave a subtle dependency in the code.
128    This function exists to keep a clear boundary.  */
129
130 static void
131 gdbscm_disasm_memory_error (int status, bfd_vma memaddr,
132                             struct disassemble_info *info)
133 {
134   memory_error (status, memaddr);
135 }
136
137 /* disassemble_info.print_address_func for gdbscm_print_insn_from_port.
138    Since we need to use our own application_data value, we need to supply
139    this routine as well.  */
140
141 static void
142 gdbscm_disasm_print_address (bfd_vma addr, struct disassemble_info *info)
143 {
144   struct gdbscm_disasm_data *data = info->application_data;
145   struct gdbarch *gdbarch = data->gdbarch;
146
147   print_address (gdbarch, addr, info->stream);
148 }
149
150 /* Subroutine of gdbscm_arch_disassemble to simplify it.
151    Call gdbarch_print_insn using a port for input.
152    PORT must be seekable.
153    OFFSET is the offset in PORT from which addresses begin.
154    For example, when printing from a bytevector, addresses passed to the
155    bv seek routines must be in the range [0,size).  However, the bytevector
156    may represent an instruction at address 0x1234.  To handle this case pass
157    0x1234 for OFFSET.
158    This is based on gdb_print_insn, see it for details.  */
159
160 static int
161 gdbscm_print_insn_from_port (struct gdbarch *gdbarch,
162                              SCM port, ULONGEST offset, CORE_ADDR memaddr,
163                              struct ui_file *stream, int *branch_delay_insns)
164 {
165   struct disassemble_info di;
166   int length;
167   struct gdbscm_disasm_data data;
168
169   di = gdb_disassemble_info (gdbarch, stream);
170   data.gdbarch = gdbarch;
171   data.port = port;
172   data.offset = offset;
173   di.application_data = &data;
174   di.read_memory_func = gdbscm_disasm_read_memory;
175   di.memory_error_func = gdbscm_disasm_memory_error;
176   di.print_address_func = gdbscm_disasm_print_address;
177
178   length = gdbarch_print_insn (gdbarch, memaddr, &di);
179
180   if (branch_delay_insns)
181     {
182       if (di.insn_info_valid)
183         *branch_delay_insns = di.branch_delay_insns;
184       else
185         *branch_delay_insns = 0;
186     }
187
188   return length;
189 }
190
191 /* (arch-disassemble <gdb:arch> address
192      [#:port port] [#:offset address] [#:size integer] [#:count integer])
193      -> list
194
195    Returns a list of disassembled instructions.
196    If PORT is provided, read bytes from it.  Otherwise read target memory.
197    If PORT is #f, read target memory.
198    PORT must be seekable.  IWBN to remove this restriction, and a future
199    release may.  For now the restriction is in place because it's not clear
200    all disassemblers are strictly sequential.
201    If SIZE is provided, limit the number of bytes read to this amount.
202    If COUNT is provided, limit the number of instructions to this amount.
203
204    Each instruction in the result is an alist:
205    (('address . address) ('asm . disassembly) ('length . length)).
206    We could use a hash table (dictionary) but there aren't that many fields. */
207
208 static SCM
209 gdbscm_arch_disassemble (SCM self, SCM start_scm, SCM rest)
210 {
211   arch_smob *a_smob
212     = arscm_get_arch_smob_arg_unsafe (self, SCM_ARG1, FUNC_NAME);
213   struct gdbarch *gdbarch = arscm_get_gdbarch (a_smob);
214   const SCM keywords[] = {
215     port_keyword, offset_keyword, size_keyword, count_keyword, SCM_BOOL_F
216   };
217   int port_arg_pos = -1, offset_arg_pos = -1;
218   int size_arg_pos = -1, count_arg_pos = -1;
219   SCM port = SCM_BOOL_F;
220   ULONGEST offset = 0;
221   unsigned int count = 1;
222   unsigned int size;
223   ULONGEST start_arg;
224   CORE_ADDR start, end;
225   CORE_ADDR pc;
226   unsigned int i;
227   int using_port;
228   SCM result;
229
230   gdbscm_parse_function_args (FUNC_NAME, SCM_ARG2, keywords, "U#OUuu",
231                               start_scm, &start_arg, rest,
232                               &port_arg_pos, &port,
233                               &offset_arg_pos, &offset,
234                               &size_arg_pos, &size,
235                               &count_arg_pos, &count);
236   /* START is first stored in a ULONGEST because we don't have a format char
237      for CORE_ADDR, and it's not really worth it to have one yet.  */
238   start = start_arg;
239
240   if (port_arg_pos > 0)
241     {
242       SCM_ASSERT_TYPE (gdbscm_is_false (port)
243                        || gdbscm_is_true (scm_input_port_p (port)),
244                        port, port_arg_pos, FUNC_NAME, _("input port"));
245     }
246   using_port = gdbscm_is_true (port);
247
248   if (offset_arg_pos > 0
249       && (port_arg_pos < 0
250           || gdbscm_is_false (port)))
251     {
252       gdbscm_out_of_range_error (FUNC_NAME, offset_arg_pos,
253                                  gdbscm_scm_from_ulongest (offset),
254                                  _("offset provided but port is missing"));
255     }
256
257   if (size_arg_pos > 0)
258     {
259       if (size == 0)
260         return SCM_EOL;
261       /* For now be strict about start+size overflowing.  If it becomes
262          a nuisance we can relax things later.  */
263       if (start + size < start)
264         {
265           gdbscm_out_of_range_error (FUNC_NAME, 0,
266                                 scm_list_2 (gdbscm_scm_from_ulongest (start),
267                                             gdbscm_scm_from_ulongest (size)),
268                                      _("start+size overflows"));
269         }
270       end = start + size - 1;
271     }
272   else
273     end = ~(CORE_ADDR) 0;
274
275   if (count == 0)
276     return SCM_EOL;
277
278   result = SCM_EOL;
279
280   for (pc = start, i = 0; pc <= end && i < count; )
281     {
282       int insn_len = 0;
283       char *as = NULL;
284       struct ui_file *memfile = mem_fileopen ();
285       struct cleanup *cleanups = make_cleanup_ui_file_delete (memfile);
286       volatile struct gdb_exception except;
287
288       TRY_CATCH (except, RETURN_MASK_ALL)
289         {
290           if (using_port)
291             {
292               insn_len = gdbscm_print_insn_from_port (gdbarch, port, offset,
293                                                       pc, memfile, NULL);
294             }
295           else
296             insn_len = gdb_print_insn (gdbarch, pc, memfile, NULL);
297         }
298       GDBSCM_HANDLE_GDB_EXCEPTION_WITH_CLEANUPS (except, cleanups);
299
300       as = ui_file_xstrdup (memfile, NULL);
301
302       result = scm_cons (dascm_make_insn (pc, as, insn_len),
303                          result);
304
305       pc += insn_len;
306       i++;
307       do_cleanups (cleanups);
308       xfree (as);
309     }
310
311   return scm_reverse_x (result, SCM_EOL);
312 }
313 \f
314 /* Initialize the Scheme architecture support.  */
315
316 static const scheme_function disasm_functions[] =
317 {
318   { "arch-disassemble", 2, 0, 1, gdbscm_arch_disassemble,
319     "\
320 Return list of disassembled instructions in memory.\n\
321 \n\
322   Arguments: <gdb:arch> start-address\n\
323       [#:port port] [#:offset address]\n\
324       [#:size <integer>] [#:count <integer>]\n\
325     port: If non-#f, it is an input port to read bytes from.\n\
326     offset: Specifies the address offset of the first byte in the port.\n\
327       This is useful if the input is from something other than memory\n\
328       (e.g., a bytevector) and you want the result to be as if the bytes\n\
329       came from that address.  The value to pass for start-address is\n\
330       then also the desired disassembly address, not the offset in, e.g.,\n\
331       the bytevector.\n\
332     size: Limit the number of bytes read to this amount.\n\
333     count: Limit the number of instructions to this amount.\n\
334 \n\
335   Returns:\n\
336     Each instruction in the result is an alist:\n\
337       (('address . address) ('asm . disassembly) ('length . length))." },
338
339   END_FUNCTIONS
340 };
341
342 void
343 gdbscm_initialize_disasm (void)
344 {
345   gdbscm_define_functions (disasm_functions, 1);
346
347   port_keyword = scm_from_latin1_keyword ("port");
348   offset_keyword = scm_from_latin1_keyword ("offset");
349   size_keyword = scm_from_latin1_keyword ("size");
350   count_keyword = scm_from_latin1_keyword ("count");
351
352   address_symbol = scm_from_latin1_symbol ("address");
353   asm_symbol = scm_from_latin1_symbol ("asm");
354   length_symbol = scm_from_latin1_symbol ("length");
355 }