Add some more casts (1/2)
[external/binutils.git] / gdb / guile / scm-disasm.c
1 /* Scheme interface to architecture.
2
3    Copyright (C) 2014-2015 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
83     = (struct gdbscm_disasm_read_data *) datap;
84   struct disassemble_info *dinfo = data->dinfo;
85   struct gdbscm_disasm_data *disasm_data
86     = (struct gdbscm_disasm_data *) dinfo->application_data;
87   SCM seekto, newpos, port = disasm_data->port;
88   size_t bytes_read;
89
90   seekto = gdbscm_scm_from_ulongest (data->memaddr - disasm_data->offset);
91   newpos = scm_seek (port, seekto, scm_from_int (SEEK_SET));
92   if (!scm_is_eq (seekto, newpos))
93     return "seek error";
94
95   bytes_read = scm_c_read (port, data->myaddr, data->length);
96
97   if (bytes_read != data->length)
98     return "short read";
99
100   /* If we get here the read succeeded.  */
101   return NULL;
102 }
103
104 /* disassemble_info.read_memory_func for gdbscm_print_insn_from_port.  */
105
106 static int
107 gdbscm_disasm_read_memory (bfd_vma memaddr, bfd_byte *myaddr,
108                            unsigned int length,
109                            struct disassemble_info *dinfo)
110 {
111   struct gdbscm_disasm_read_data data;
112   void *status;
113
114   data.memaddr = memaddr;
115   data.myaddr = myaddr;
116   data.length = length;
117   data.dinfo = dinfo;
118
119   status = gdbscm_with_guile (gdbscm_disasm_read_memory_worker, &data);
120
121   /* TODO: IWBN to distinguish problems reading target memory versus problems
122      with the port (e.g., EOF).
123      We return TARGET_XFER_E_IO here as that's what memory_error looks for.  */
124   return status != NULL ? TARGET_XFER_E_IO : 0;
125 }
126
127 /* disassemble_info.memory_error_func for gdbscm_print_insn_from_port.
128    Technically speaking, we don't need our own memory_error_func,
129    but to not provide one would leave a subtle dependency in the code.
130    This function exists to keep a clear boundary.  */
131
132 static void
133 gdbscm_disasm_memory_error (int status, bfd_vma memaddr,
134                             struct disassemble_info *info)
135 {
136   memory_error (status, memaddr);
137 }
138
139 /* disassemble_info.print_address_func for gdbscm_print_insn_from_port.
140    Since we need to use our own application_data value, we need to supply
141    this routine as well.  */
142
143 static void
144 gdbscm_disasm_print_address (bfd_vma addr, struct disassemble_info *info)
145 {
146   struct gdbscm_disasm_data *data
147     = (struct gdbscm_disasm_data *) info->application_data;
148   struct gdbarch *gdbarch = data->gdbarch;
149
150   print_address (gdbarch, addr, (struct ui_file *) info->stream);
151 }
152
153 /* Subroutine of gdbscm_arch_disassemble to simplify it.
154    Call gdbarch_print_insn using a port for input.
155    PORT must be seekable.
156    OFFSET is the offset in PORT from which addresses begin.
157    For example, when printing from a bytevector, addresses passed to the
158    bv seek routines must be in the range [0,size).  However, the bytevector
159    may represent an instruction at address 0x1234.  To handle this case pass
160    0x1234 for OFFSET.
161    This is based on gdb_print_insn, see it for details.  */
162
163 static int
164 gdbscm_print_insn_from_port (struct gdbarch *gdbarch,
165                              SCM port, ULONGEST offset, CORE_ADDR memaddr,
166                              struct ui_file *stream, int *branch_delay_insns)
167 {
168   struct disassemble_info di;
169   int length;
170   struct gdbscm_disasm_data data;
171
172   di = gdb_disassemble_info (gdbarch, stream);
173   data.gdbarch = gdbarch;
174   data.port = port;
175   data.offset = offset;
176   di.application_data = &data;
177   di.read_memory_func = gdbscm_disasm_read_memory;
178   di.memory_error_func = gdbscm_disasm_memory_error;
179   di.print_address_func = gdbscm_disasm_print_address;
180
181   length = gdbarch_print_insn (gdbarch, memaddr, &di);
182
183   if (branch_delay_insns)
184     {
185       if (di.insn_info_valid)
186         *branch_delay_insns = di.branch_delay_insns;
187       else
188         *branch_delay_insns = 0;
189     }
190
191   return length;
192 }
193
194 /* (arch-disassemble <gdb:arch> address
195      [#:port port] [#:offset address] [#:size integer] [#:count integer])
196      -> list
197
198    Returns a list of disassembled instructions.
199    If PORT is provided, read bytes from it.  Otherwise read target memory.
200    If PORT is #f, read target memory.
201    PORT must be seekable.  IWBN to remove this restriction, and a future
202    release may.  For now the restriction is in place because it's not clear
203    all disassemblers are strictly sequential.
204    If SIZE is provided, limit the number of bytes read to this amount.
205    If COUNT is provided, limit the number of instructions to this amount.
206
207    Each instruction in the result is an alist:
208    (('address . address) ('asm . disassembly) ('length . length)).
209    We could use a hash table (dictionary) but there aren't that many fields. */
210
211 static SCM
212 gdbscm_arch_disassemble (SCM self, SCM start_scm, SCM rest)
213 {
214   arch_smob *a_smob
215     = arscm_get_arch_smob_arg_unsafe (self, SCM_ARG1, FUNC_NAME);
216   struct gdbarch *gdbarch = arscm_get_gdbarch (a_smob);
217   const SCM keywords[] = {
218     port_keyword, offset_keyword, size_keyword, count_keyword, SCM_BOOL_F
219   };
220   int port_arg_pos = -1, offset_arg_pos = -1;
221   int size_arg_pos = -1, count_arg_pos = -1;
222   SCM port = SCM_BOOL_F;
223   ULONGEST offset = 0;
224   unsigned int count = 1;
225   unsigned int size;
226   ULONGEST start_arg;
227   CORE_ADDR start, end;
228   CORE_ADDR pc;
229   unsigned int i;
230   int using_port;
231   SCM result;
232
233   gdbscm_parse_function_args (FUNC_NAME, SCM_ARG2, keywords, "U#OUuu",
234                               start_scm, &start_arg, rest,
235                               &port_arg_pos, &port,
236                               &offset_arg_pos, &offset,
237                               &size_arg_pos, &size,
238                               &count_arg_pos, &count);
239   /* START is first stored in a ULONGEST because we don't have a format char
240      for CORE_ADDR, and it's not really worth it to have one yet.  */
241   start = start_arg;
242
243   if (port_arg_pos > 0)
244     {
245       SCM_ASSERT_TYPE (gdbscm_is_false (port)
246                        || gdbscm_is_true (scm_input_port_p (port)),
247                        port, port_arg_pos, FUNC_NAME, _("input port"));
248     }
249   using_port = gdbscm_is_true (port);
250
251   if (offset_arg_pos > 0
252       && (port_arg_pos < 0
253           || gdbscm_is_false (port)))
254     {
255       gdbscm_out_of_range_error (FUNC_NAME, offset_arg_pos,
256                                  gdbscm_scm_from_ulongest (offset),
257                                  _("offset provided but port is missing"));
258     }
259
260   if (size_arg_pos > 0)
261     {
262       if (size == 0)
263         return SCM_EOL;
264       /* For now be strict about start+size overflowing.  If it becomes
265          a nuisance we can relax things later.  */
266       if (start + size < start)
267         {
268           gdbscm_out_of_range_error (FUNC_NAME, 0,
269                                 scm_list_2 (gdbscm_scm_from_ulongest (start),
270                                             gdbscm_scm_from_ulongest (size)),
271                                      _("start+size overflows"));
272         }
273       end = start + size - 1;
274     }
275   else
276     end = ~(CORE_ADDR) 0;
277
278   if (count == 0)
279     return SCM_EOL;
280
281   result = SCM_EOL;
282
283   for (pc = start, i = 0; pc <= end && i < count; )
284     {
285       int insn_len = 0;
286       char *as = NULL;
287       struct ui_file *memfile = mem_fileopen ();
288       struct cleanup *cleanups = make_cleanup_ui_file_delete (memfile);
289
290       TRY
291         {
292           if (using_port)
293             {
294               insn_len = gdbscm_print_insn_from_port (gdbarch, port, offset,
295                                                       pc, memfile, NULL);
296             }
297           else
298             insn_len = gdb_print_insn (gdbarch, pc, memfile, NULL);
299         }
300       CATCH (except, RETURN_MASK_ALL)
301         {
302           GDBSCM_HANDLE_GDB_EXCEPTION_WITH_CLEANUPS (except, cleanups);
303         }
304       END_CATCH
305
306       as = ui_file_xstrdup (memfile, NULL);
307
308       result = scm_cons (dascm_make_insn (pc, as, insn_len),
309                          result);
310
311       pc += insn_len;
312       i++;
313       do_cleanups (cleanups);
314       xfree (as);
315     }
316
317   return scm_reverse_x (result, SCM_EOL);
318 }
319 \f
320 /* Initialize the Scheme architecture support.  */
321
322 static const scheme_function disasm_functions[] =
323 {
324   { "arch-disassemble", 2, 0, 1, as_a_scm_t_subr (gdbscm_arch_disassemble),
325     "\
326 Return list of disassembled instructions in memory.\n\
327 \n\
328   Arguments: <gdb:arch> start-address\n\
329       [#:port port] [#:offset address]\n\
330       [#:size <integer>] [#:count <integer>]\n\
331     port: If non-#f, it is an input port to read bytes from.\n\
332     offset: Specifies the address offset of the first byte in the port.\n\
333       This is useful if the input is from something other than memory\n\
334       (e.g., a bytevector) and you want the result to be as if the bytes\n\
335       came from that address.  The value to pass for start-address is\n\
336       then also the desired disassembly address, not the offset in, e.g.,\n\
337       the bytevector.\n\
338     size: Limit the number of bytes read to this amount.\n\
339     count: Limit the number of instructions to this amount.\n\
340 \n\
341   Returns:\n\
342     Each instruction in the result is an alist:\n\
343       (('address . address) ('asm . disassembly) ('length . length))." },
344
345   END_FUNCTIONS
346 };
347
348 void
349 gdbscm_initialize_disasm (void)
350 {
351   gdbscm_define_functions (disasm_functions, 1);
352
353   port_keyword = scm_from_latin1_keyword ("port");
354   offset_keyword = scm_from_latin1_keyword ("offset");
355   size_keyword = scm_from_latin1_keyword ("size");
356   count_keyword = scm_from_latin1_keyword ("count");
357
358   address_symbol = scm_from_latin1_symbol ("address");
359   asm_symbol = scm_from_latin1_symbol ("asm");
360   length_symbol = scm_from_latin1_symbol ("length");
361 }