Re: Semihosting output on ARM7TDMI

Grant Edwards
2001-08-14T11:43:00Z

On Tue, Aug 14, 2001 at 09:31:26AM -0700, Keith Seitz wrote:
> On Tue, 14 Aug 2001, Grant Edwards wrote:
>
> > But, the RDI stuff isn't aware of gdb, and it would take some
> > work to make it aware. It would be "a good thing" but somebody
> > would have to want it bad enough to actuallly do it.
>
> Isn't there already some machinery in place to do target I/O? You can
> certainly do printf and the like on an arm board using rdi and gdb.

I wasn't aware that that stuff worked. What I've seen in the
past is that the semi-hosting routines generates the "CL_Write"
messages, and the handler for that flushes the data.

> What do the the members writec, readc, write, gets in struct
> Dbg_HostosInterface mean? Specifically:

It appears that they're the routines that are supposed to get
called for semi-hosting console I/O.

> gdb_hostif.dbgprint = myprint;
> gdb_hostif.dbgpause = mypause;
> gdb_hostif.dbgarg = NULL;
> gdb_hostif.writec = mywritec;
> gdb_hostif.readc = myreadc;
> gdb_hostif.write = mywrite;
> gdb_hostif.gets = mygets;
> gdb_hostif.hostosarg = NULL;
> gdb_hostif.reset = voiddummy;
>>
> Doesn't any of this deal with "semi-hosting"?

It's supposed to, but I don't think it all works. From what
I've seen, the semi-hosting client stuff generates writes to fd
0, and since that fd has never been opened, the data is
discarded in hsys.c by HandleSysMessage:

490 case CL_Write:
491 {
492 /* Write(word handle, word nbtotal, word nbytes, bytes data)
493 * return(word nbytes)
494 * WriteX(word nbytes, bytes data)
495 * return(word nbytes)
496 */
497 unsigned char *rwdata = NULL, *rwhead = NULL;
498 unsigned char *write_source = NULL;
499 char flags;
500 FILE *fhreal;
501 unsigned int ack_reason = CL_Write; /* first ack is for CL_Write */
502
503 err = -1; /* err == 0 is fwrite() error indication */
504 unpack_message(buffp, "%w%w%w", &fh, &nbtotal, &nbytes);
505 DebugPrintF(("CL_Write: fh %d nbtotal %u nbytes %u\n",
506 fh, nbtotal, nbytes));
507
** 508 fhreal = hsysGetRealFileHandle(stateptr, fh, &flags);
509 nbtogo = nbtotal;
510
511 /* deal with the file handle */
** 512 if (fhreal == NULL)
** 513 err = 0;
514 else {
515 if (flags & READOP)
516 fseek(fhreal,0,SEEK_CUR);
517 stateptr->OSptr->FileFlags[fh] = (flags & BINARY) | WRITEOP;

line 508 returns a NULL, since no file has been opened, and the
data is flushed.

[It looks like CL_WriteC and CL_ReadC do what they should:
calling hostif->writec and hostif->readc, but I've never seen
anybody post ADP traces that showed those being used.]

Aha! I just noticed something that I missed before...

It also looks like somebody _did_ create a special case when an
fd maps to stdout or stderr by calling hostif->write() instead
of calling fwrite() on the file handle directly. The RDI stuff
is more aware than I thought. It isn't aware specifically of
gdb, but the remote-rdi.c adapts the RDI API well enough that I
think semi-hosting can be made to work right.

535 do {
536 /* at least once!! */
537
538 if (nbtogo == 0 && err != 0) {
539 /* Do the actual write! */
** 540 if (fhreal == stdout || fhreal == stderr) {
** 541 stateptr->hostif->write(stateptr->hostif->hostosarg,
542 (char *)write_source, nbtotal);
543 }
544 else
** 545 err = fwrite(write_source, 1, nbtotal, fhreal);
546 stateptr->last_errno = errno;
547 DebugCheckErr("fwrite", TRUE, (err == 0), stateptr->last_errno);
548 }
549

I think that if you initialize fd #0 to be stdout, then the
hostif->write() routine will get called, and that in turn calls
fputc_unfiltered(c,gdb_stdout). I don't know why the
semi-hosting client routines are writing to fd 0 (which I would
assume to be stdin) rather than 1 (stdout) or 2 (stderr).

So one could try changing my three-line kludge to initialize
the first fd to stdout instead of stdin.

The handling for CL_Read is different and doesn't check for
stdin, stdout, stderr. Instead, if the fd maps to a file handle
that's a tty, then hostif->gets() is called which then does an
fgets() on stdin. Otherwise fread() is called on the file
handle.