From mboxrd@z Thu Jan 1 00:00:00 1970 From: Grant Edwards To: Keith Seitz Cc: Andrew Cagney , gdb@sourceware.cygnus.com Subject: Re: Semihosting output on ARM7TDMI Date: Tue, 14 Aug 2001 11:43:00 -0000 Message-id: <20010814134522.A8849@visi.com> References: <20010814112608.A8586@visi.com> X-SW-Source: 2001-08/msg00131.html 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