========   GDB MDI-SERVER  README   ============

Our solution to get GDB talking to MAJIC consists of a program named
mdi-server.  It implements GDB's remote protocol on top of the MDI
(Meta Debug Interface) API.  The advantage of this is that you don't 
need to build a MAJIC-specific GDB, you just use an off-the-shelf GDB 
and connect to mdi-server with the "target remote" command.

Before attempting to use mdi-server, follow the steps described in the
"Majic User's Manual" (manuals/MAJIC_UserManual.pdf) to configure
and test the MAJIC with your target system, and then those decribed in
"MDI for MAJIC User's Guide" (manuals/mdiuser.pdf) set up the
epimdi.cfg configuration file for the MDI library.

NOTE: mdi-server requires the ISA value to be specified in
the Device Definition Section in the epimdi.cfg file for MIPS 
targets.  It is used to determine if target registers are 32 
or 64 bits wide.

NOTE: GDB is a moving target.  The commands and variables supported by a
particular GDB depend on its version and on how it was configured when it
was built.  The commands and variables mentioned in this readme were valid
in GDB 4.18 (target xscale-elf) and 5.0 (target mipsisa32-elf), but YMMV.


==================================
QUICK START:

mdi-server works on Solaris 2.5 or later, Linux with glibc 2.1 or 
later, and on PC's running RedHat's Cygwin environment.  Linux and 
Solaris users should make sure the ./bin subdirectory under the EPI
tools directory is included on the PATH.  Cygwin users may also find
this more convenient, but it is not required.

Run mdi-server from your working directory containing your startice.cmd
and epimdi.cfg files.  These examples assume you only have one
uncommented DevName section in epimdi.cfg:

Linux/Solaris (epi/bin on PATH):
mdi-server -l /path/to/epitools/bin/mdi.so

Cygwin (epi/bin not on PATH):
/path/to/epitools/bin/mdi-server

mdi-server defaults to listening on port 2345.  With an ARM-targeted GDB,
you shouldn't need to use any of the configuration options described
below.  With a MIPS GDB configured for target=mipsisa32, you need to
add "-r 8" to the command above.  If you are using some other GDB, see
below first.

Once mdi-server is running, it simply waits for a GDB to connect.  In
a separate console window, you can launch GDB as usual in your
application directory, specify your file to debug, and connect to
mdi-server:

(gdb) set remoteti 10              # see note in "KNOWN ISSUES"
(gdb) set heur 0                   # if MIPS, see note in "KNOWN ISSUES"
(gdb) file ...                     # specify program file to debug
(gdb) target remote localhost:2345

and commence debugging (load, set breaks, cont, step, next, etc).

==================================

Here's the full usage prompt from mdi-server:

>./mdi-server.exe -h
Usage: ./mdi-server [-v] [-p port_num] [-t target_num] [-d device_num]
        [-h]            Displays version number and usage.
        [-v]            Writes debugging output to stdout.
        [-p port_num]   Use port_num. Default is 2345.
        [-f s|d]        Float regs are single|double precision (default single)
        [-n num_regs]   GDB "NUM_REGS" value (MIPS/ARM default 107/26)
        [-r 4|8]        GDB "RAW_REGSIZE" value (default 4)
        [-t target_num] Set target number, if MDILib supports Target Groups.
        [-d device_num] Set device number.
        [-l lib_file]   MDILib filename. Default is mdi.so.
        If more than one target or device is available, but target
        and/or device number are not provided, ./mdi-server will
        run in interactive mode.  When GDB connects, it will list
        the available targets and devices and prompt the user to
        select from the list.
>

-p gives the TCP port number mdi-server listens on.  You need to give
the port number in GDB's "target remote host:port" command.  The port
number is arbitrary, so there's no reason to change the default.

-f specifies whether a MIPS-targeted GDB is configured to expect floating
point registers to be passed as single or double precision in the remote
protocol.  See notes below.

-n specifies how many target registers GDB knows about (the value of
the NUM_REGS macro in the GDB source).  mdi-server was configured to 
support the largest known register set (107 for MIPS and 26 for ARM).
See notes below.

-r specifies the size of registers passed in the remote protocol.  See
notes below.

-t specifies which "Target Group" to connect to. This is an MDI term,
see mdiuser.pdf for details.  The -t option is not used with our MAJIC
MDILib since it does not implement "Target Groups".

-d specifies which "Device" to connect to. This is an MDI term, see
mdiuser.pdf for details.  The configuration file epimdi.cfg controls
what MDI "Devices" will be available to choose from.  If you only 
specify a single DevName in epimdi.cfg, there will only be one device
and you can omit the -d option.  If you have multiple DevName sections, 
you should use the -d option to specify which one you want to use.   
Otherwise mdi-server will prompt for a choice when GDB connects, and
this can lead to timeouts with some GDB configurations.

Linux and Solaris users will need the -l option even though the MDI
library file has the default name (mdi.so), because the shared library
loader doesn't normally search the current directory, program directory,
or PATH.  For convenience, you can use the ldconfig or crle OS command
to add the /path/to/epitools/bin directory to the library search path,
and then you will not need to specify the -l option.


==================================
GETTING THE REGISTERS RIGHT FOR MIPS TARGETS

In the GDB remote protocol, when GDB sends a request for the register
values the reply packet consists of one *long* string of hex digits 
with all the values concatenated together.  It is assumed that GDB and
the remote server have been configured to have the same hard-coded
knowledge of the number, order, and size of all the registers.  If the
remote sends too much data, GDB will display a "Remote packet too long"
error message when connecting.  If it sends too little data, or some of
the registers are sent with the wrong size, GDB will not complain but it
will not be able to display correct values for all the registers.

mdi-server is intended to interoperate with as many GDB variants as 
possible, without having to be configured and built from source for
each variant.  The -f, -n, and -r options allow mdi-server to be
configured at run-time to match the assumptions GDB is making.

In practice, the default values for -f, -n, and -r should work fine 
for all ARM targets, but there are significant differences between
various MIPS target configurations.

You may be able to determine the correct settings for these options
from the GDB source code.  If you are using the GNU tools distributed
by Mips Technologies (configured as mipsisa32), the defaults for -f
and -n are correct but you need to specify "-r 8".  Otherwise, try the
following procedure:

Start mdi-server the first time with just "-n 38".  This specifies the
minimum possible set of registers, sent as four bytes each, so GDB will 
not report a "packet too long" error.  If GDB reports "Couldn't establish
connection to remote target" with no apparent reason, add the "-r 8"
option.

After connecting, check how many registers GDB supports by entering the 
"info all-reg" command.  GDB will display all the registers it knows 
about.  If the last register displayed is "pc", then "-n 38" is correct.
If it is "fp", use "-n 72" if your target has a floating point unit, 
else "-n 38".  If the last register is "PRid", use "-n 90", and if it is 
"Config1", then the default ("-n 107") is correct.

If your GDB supports more than 72 registers it is important to get the
"-f" option right even though your processor most likely does not have
a floating point coprocessor.  Now that you have the correct settings for
the -r and -n options, try adding "-f 8".  If it is not correct, GDB 
will report the "Remote packet too long" error and refuse to connect.

That should do it.  If you can't connect successfully using this
procedure, please enable remote debugging with the command 
"set debug remote 1" before attempting the connection with 
"target remote".  This will display the packets being sent and 
received.  Include this output if you need to contact EPI support.


==================================
EXECUTING MON COMMANDS:

The GDB "monitor" command can be used to pass MON commands through to
the MDILib.  This allows access to MAJIC features that are not available
in GDB, such as trace display, and access to all CPU registers rather than
the limited set GDB knows about.

If you want MON commands to have access to symbols in your
program, either add an LS (Load Symbols) command to the startice.cmd
or just pass it though manually.


==================================
DOWNLOAD SPEED:

By default, GDB generally downloads program code & data in small
chunks (a few hundred bytes) that are not necessarily a multiple of 
four bytes in length.  This causes program download times to be slower
than necessary, especially with ARM targets.

There are two GDB internal variables that affect this:
memory-write-packet-size and download-write-size.  Setting
memory-write-packet-size to "fixed" allows the packet size to be 
increased beyond GDB's default limit.  mdi-server has no fixed limit,
it will increase its packet buffer size as needed.  To improve GDB
download performance, you should set download-write-size to a value 
like 4096 or 8192, and memory-write-packet-size to a larger value to
allow for packet overhead (+100 bytes is plenty).  For example, to 
download 4KB at a time:

  (gdb) set remote memory-write-packet-size fixed
  (gdb) set remote memory-write-packet-size 4200
  (gdb) set download-write-size 4096

NOTE: "set remote memory-write-packet-size" is new in GDB 5.x.  
In GDB 4.x, use "set remotewritesize" instead:

  (gdb) set remotewritesize fixed
  (gdb) set remotewritesize 4200
  (gdb) set download-write-size 4096


An even better way to get the fastest possible program download speed 
is to tell the MAJIC back-end to do the download via MON's Load command:

  (gdb) mon L pathname-of-program

Since this avoids the overhead of the GDB remote protocol, which is 
not very efficient even with the tweaks mentioned above, using MON's
Load command is the recommended method for large programs.


==================================
KNOWN ISSUES:

When GDB first connects, it can take a few seconds for mdi-server to 
open the MDI connection to the MAJIC and process the startice.cmd
startup command file.  With some versions of GDB, if a reply to a
remote protocol packet does not arrive within a timeout interval
it is resent.  This causes an "Invalid remote reply" warning to be
displayed because GDB is not expecting both packets to be replied
to.  If you get this warning, increase the timeout value via the GDB
internal variable "remotetimeout":
  (gdb) set remoteti 10
Other versions of GDB do not apply the timeout, even though the
variable exists.

GDB has an internal variable named "heuristic-fence-post".  It controls
how far backwards from the current PC GDB will scan memory looking
for a function start.  This variable should default to 0, but it may
not.  If it is not 0, it can cause GDB to try to access invalid memory 
locations.  This is primarily a concern for MIPS targets, where the 
initial PC value when connecting is usually 0xbfc00000 (the reset vector),
and addresses in the 0xbfbxxxxx range are invalid.  In that case, you have
to set heuristic-fence-post to zero before connecting:
  (gdb) set heur 0

mdi-server can run on the same host as GDB or a different host, but
if it is running on a different host you should open a telnet (or
other remote login) session to it from the host you run GDB at.  The
reason is that the MDILib needs to be able to display output to and
sometimes get input from the user, and currently this I/O is being
done by mdi-server rather than being passed though to GDB.  Most 
output actually does get routed back to GDB (when the target is running
and when processing a pass-through MON command), but there doesn't seem
to be any facility in the GDB remote protocol for the remote to request
user input from GDB.

There is code in mdi-server to handle hardware breakpoint requests,
but apparently there are no MIPS- or ARM-targeted GDB configurations that
have this capability enabled.  So it would require a GDB patch to test.

==================================
