This is the mail archive of the gdb@sources.redhat.com 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]

Re: Semihosting output on ARM7TDMI


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.

-- 
Grant Edwards
grante@visi.com


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