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