This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [WIP] TI msp430 CIO support


On 05/17/2013 12:23 PM, Kevin Buettner wrote:
I don't intend to commit this patch as is, but I wanted to post it
because it provides useful functionality for msp430 programming and
debugging.  I have found it very useful for running the GDB test suite
because it provides the necessary functionality for printf() and
write() to work.

TI has an I/O mechanism used by their compiler and libraries that they
call CIO.  In a nutshell, it defines a small number of operations
such as open, close, read, write, plus a few others.  Drivers exist at
several levels for implementing this functionality.  E.g. there are
a board level drivers that causes I/O to occur against devices on the
board.  When the target is connected to a debugger, a debug-based
driver is available which causes I/O to be performed on the host
running GDB (or some other debugger).

The debugger based driver uses a simple breakpoint driven
implementation.  The debugger places a breakpoint on a known location
which is always called when debugger-based I/O is to be performed.
When the breakpoint at that location is hit, the debugger reads the
details of the system call and its parameters from a memory based
buffer.  The debugger writes back the output of the system call to the
same buffer.  (See my patch for the exact details.)

Kevin,
TI C6X uses the same CIO mechanism too, but it was implemented in the stub side instead of the GDB side. The stub has to query to GDB about the address some special symbols and manage the breakpoint by itself. Your explanation to CIO is quite clear, and I suggest that we can move this explanation to the head comment of msp430-cio.c.


One of my early implementations of this functionality used a normal
(but hidden) GDB breakpoint with a command list whose last command
was "continue".  This is similar to the way that dprintf is implemented.
This implementation had a serious flaw, however, in that it doesn't
work correctly when attempting to use "next" to step over a statement
which performs one of these CIO operations.  (I think that other commands
such as "finish" and "until" have similar issues.)

The current dprintf implementation can be used to illustrate this
flaw.  Here's an example using the test case from gdb.base/break.exp:


We realized this flaw and try to fix it. Hui is pushing the fix forward and the recent patch is posted here.

  [RFC] PR 15075 dprintf interferes with "next"
  http://sourceware.org/ml/gdb-patches/2013-05/msg00574.html

Hope this patch fixes the issue you encountered.


I finally settled on using the shared library machinery because I was
able to obtain correct behavior.  The only good thing about doing it
this way is that it works correctly.  I do not want this patch to go
in as is because the shared library mechanism should not be subverted
for this purpose.  That's why this patch is a work-in-progress instead
of one for which I seek comments or approval.

In order for this work to go into the GDB sources, the use of the
shared library machinery needs to be removed and replaced with some
other kind of breakpoint machinery which still provides correct
behavior.   This same mechanism could be used to improve dprintf
behavior as well.

That sounds good.


diff -uprN ../../src/gdb/msp430-cio.c ./msp430-cio.c
--- ../../src/gdb/msp430-cio.c	1969-12-31 17:00:00.000000000 -0700
+++ ./msp430-cio.c	2013-05-16 09:37:39.100986167 -0700

Looks CIO is widely used in different TI processors, so probably we can rename this file to cio.c or ti-cio.c.

+
+/* Create the C I/O breakpoint when the `inferior_created' observer
+   is invoked.  */
+
+static void
+cio_inferior_created (struct target_ops *target, int from_tty)
+{
+  int status;
+  struct minimal_symbol *ciobuf_sym, *cio_bp_sym;
+  struct breakpoint *cio_breakpoint;
+  struct cio_state *cio_state = get_cio_state ();
+
+  /* Look up the CIO buffer using several different variations.  */
+  ciobuf_sym = lookup_minimal_symbol ("_CIOBUF_", NULL, NULL);
+
+  if (ciobuf_sym == NULL)
+    ciobuf_sym = lookup_minimal_symbol ("__CIOBUF_", NULL, NULL);
+
+  if (ciobuf_sym == NULL)
+    ciobuf_sym = lookup_minimal_symbol ("__CIOBUF__", NULL, NULL);
+
+  /* Look up the symbol at which to place a breakpoint.  */
+  cio_bp_sym = lookup_minimal_symbol ("C$$IO$$", NULL, NULL);
+
+  /* Delete CIO breakpoint from earlier runs.  */
+  remove_solib_event_breakpoints ();
+
+  /* Can't do CIO if the required symbols do not exist.  */
+  if (ciobuf_sym == NULL || cio_bp_sym == NULL)
+    return;
+
+  cio_state->ciobuf_addr = SYMBOL_VALUE_ADDRESS (ciobuf_sym);
+  cio_breakpoint = create_solib_event_breakpoint
+                    (get_current_arch (), SYMBOL_VALUE_ADDRESS (cio_bp_sym));

Probably, we also need to lookup symbol "C$$EXIT" and set breakpoint on it.

+/* Do the actual work associated with reading a CIO command, its parameters,
+   etc, performing the I/O operation, and then writing back the result.  */
+
+static void
+cio_do_cio (void)
+{
+  gdb_byte lcp[11];	/* length, command, params. */
+  gdb_byte *data = NULL;
+  gdb_byte *in_params, *out_params;
+  int len, cmd;

I prefer to define a struct to represent the data in CIO buffer, like this:

struct __attribute__((packed)) cio_open_to_host
{
  /* Suggested file descriptor (little endian).  */
  short fd;
  /* Flags (little endian).  */
  short flags;
  /* Mode (little endian).  */
  uint32_t mode;
};

struct __attribute__((packed)) cio_to_host
{
  /* Data length.  */
  uint32_t length;
  /* Command.  */
  gdb_byte command;
  /* Parameters.  */
  union
  {
    gdb_byte buf[8];
    struct cio_open_to_host open;
    ....
  } parms;
  /* Variable-length data.  */
  gdb_byte data[];
};

then, the code is much more readable, IMO.

--
Yao (éå)


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]