Page 2 of 3

Re: Debugging binutils under my OS?

Posted: Mon Oct 12, 2015 3:54 am
by mariuszp
gerryg400 wrote:Hi, please see the attached file. I wouldn't describe these as rigorous. Most of these failed when I first tried but they all pass now :)
Thank you. How do I initialise the "testfile.bin"? Is it supposed to be initialised to some specific size and/or data?

Re: Debugging binutils under my OS?

Posted: Mon Oct 12, 2015 4:18 am
by gerryg400

Code: Select all

    fd = open("testfile.bin", O_RDWR | O_CREAT, 0550);
    for (j=0; j<10; ++j)
    {
        for (i='!'; i<='}'; ++i)
        {
            unsigned char ch = i;
            write(fd, &ch, 1);
        }
    }
    close(fd);

Code: Select all

    fd = open("testfile2.bin", O_RDWR | O_CREAT, 0550);
    for (i=0; i<256; ++i) {
        unsigned char ch = i;
        write(fd, &ch, 1);
    }
    for (i=0; i<256; ++i) {
        unsigned char ch = 255-i;
        write(fd, &ch, 1);
    }
    for (i=0; i<256; ++i) {
        unsigned char ch = i;
        write(fd, &ch, 1);
    }
    for (i=0; i<256; ++i) {
        unsigned char ch = 255-i;
        write(fd, &ch, 1);
    }
    close(fd);

Re: Debugging binutils under my OS?

Posted: Mon Oct 12, 2015 2:28 pm
by mariuszp
I seem to be getting some confusion again.

http://pubs.opengroup.org/onlinepubs/00 ... ngetc.html

This says that one byte of push-back shall be provided. This means that multiple calls to ungetc() without fgetc()/fread()/etc do not have to succeed. My implementation buffers only one "ungot" character, but your tests seem to enforce the buffer to be bigger (3 ungetc()s in a row).

Does software tend to assume that the unget buffer is larger than 1 byte?

Re: Debugging binutils under my OS?

Posted: Mon Oct 12, 2015 2:52 pm
by gerryg400
Yep. I support 2 so you'll need to modify the tests slightly.

[edit] I just re-read your post and the question at the end. I don't think it is necessary to support more than 1 char of pushback. I supported 2 just because.

Re: Debugging binutils under my OS?

Posted: Tue Oct 13, 2015 2:16 pm
by mariuszp
I also had a really strange... "event"... while building binutils. There were lots of warnings that strcasecmp() is implicit declared (which means it's not in the headers), but there was no linking error despite the fact that my libc does not yet implement this function...

Re: Debugging binutils under my OS?

Posted: Tue Oct 13, 2015 3:02 pm
by gerryg400
Binutils links with its own copy of strcasecmp, probably in libiberty if you don't supply it.

Re: Debugging binutils under my OS?

Posted: Tue Oct 13, 2015 3:58 pm
by mariuszp
OK one of the tests failed and I'm a bit confused as to why:

Code: Select all

	rewind(f);
	test_assert(fgetc(f) == 0x21);
	test_assert(ftell(f) == 1);
	test_assert(ungetc('x', f) == 'x');
	test_assert(ftell(f) == 0);
	test_assert(fseek(f, 0, SEEK_CUR) == 0);
	test_assert(ftell(f) == 0);
the standard says fseek() must reverse the effect of ungetc(). http://pubs.opengroup.org/onlinepubs/00 ... fseek.html

after the call to ungetc(), the file position is still 1 due to the previous fgetc(), but reported position is 0 as expected. but the fseek() to SEEK_CUR should set the reported position to 1, as it is 0 bytes away from the current file position, as far as I understand. And yet the last test (test_assert(ftell(f) == 0) ) fails. What is wrong?

Re: Debugging binutils under my OS?

Posted: Wed Oct 14, 2015 2:37 am
by gerryg400
mariuszp wrote:OK one of the tests failed and I'm a bit confused as to why:

Code: Select all

	rewind(f);
	test_assert(fgetc(f) == 0x21);
	test_assert(ftell(f) == 1);
	test_assert(ungetc('x', f) == 'x');
	test_assert(ftell(f) == 0);
	test_assert(fseek(f, 0, SEEK_CUR) == 0);
	test_assert(ftell(f) == 0);
the standard says fseek() must reverse the effect of ungetc(). http://pubs.opengroup.org/onlinepubs/00 ... fseek.html

after the call to ungetc(), the file position is still 1 due to the previous fgetc(), but reported position is 0 as expected. but the fseek() to SEEK_CUR should set the reported position to 1, as it is 0 bytes away from the current file position, as far as I understand. And yet the last test (test_assert(ftell(f) == 0) ) fails. What is wrong?
I think you are probably correct. I based my implementation on the doc for fflush() which says
fflush() wrote:[CX] [Option Start] For a stream open for reading, if the file is not already at EOF, and the file is one capable of seeking, the file offset of the underlying open file description shall be set to the file position of the stream, and any characters pushed back onto the stream by ungetc() or ungetwc() that have not subsequently been read from the stream shall be discarded (without further changing the file offset).[Option End]
IOW, fflush() is optionally different from fseek() in this detail. My fseek() calls fflush() so operates incorrectly.

Re: Debugging binutils under my OS?

Posted: Wed Oct 14, 2015 3:25 am
by mariuszp
gerryg400 wrote:
mariuszp wrote:OK one of the tests failed and I'm a bit confused as to why:

Code: Select all

	rewind(f);
	test_assert(fgetc(f) == 0x21);
	test_assert(ftell(f) == 1);
	test_assert(ungetc('x', f) == 'x');
	test_assert(ftell(f) == 0);
	test_assert(fseek(f, 0, SEEK_CUR) == 0);
	test_assert(ftell(f) == 0);
the standard says fseek() must reverse the effect of ungetc(). http://pubs.opengroup.org/onlinepubs/00 ... fseek.html

after the call to ungetc(), the file position is still 1 due to the previous fgetc(), but reported position is 0 as expected. but the fseek() to SEEK_CUR should set the reported position to 1, as it is 0 bytes away from the current file position, as far as I understand. And yet the last test (test_assert(ftell(f) == 0) ) fails. What is wrong?
I think you are probably correct. I based my implementation on the doc for fflush() which says
fflush() wrote:[CX] [Option Start] For a stream open for reading, if the file is not already at EOF, and the file is one capable of seeking, the file offset of the underlying open file description shall be set to the file position of the stream, and any characters pushed back onto the stream by ungetc() or ungetwc() that have not subsequently been read from the stream shall be discarded (without further changing the file offset).[Option End]
IOW, fflush() is optionally different from fseek() in this detail. My fseek() calls fflush() so operates incorrectly.
Ohhhh hang on, my fflush() doesn't work correctly then. Other than that, my fseek() is the same as yours.

Re: Debugging binutils under my OS?

Posted: Wed Oct 14, 2015 3:52 am
by gerryg400
This behaviour is optional...

Also I don't think this part is critical. I'm guessing binutils doesn't rely on it too much...

Re: Debugging binutils under my OS?

Posted: Wed Oct 14, 2015 3:59 am
by mariuszp
gerryg400 wrote:This behaviour is optional...

Also I don't think this part is critical. I'm guessing binutils doesn't rely on it too much...
Still better to keep up with the up-to-date standard.

Also it seems like "ld" doesn't rely on ungetc() at all. Perhaps your fread() test will reveal something. Otherwise I'll probably have to "readelf" the glidix "ld" and see which libc functions it calls and maybe I could guess which one of them is buggy.

Re: Debugging binutils under my OS?

Posted: Wed Oct 14, 2015 4:07 am
by gerryg400
I do remember that ld does lots of fseek/fread/fseek/fwrite ALSO fprintf and fscanf.

Read carefully what it says for fread and fwrite. (Same applies for fprintf and fscanf.
fread() wrote:For each object, size calls shall be made to the fgetc() function and the results stored, in the order read, in an array of unsigned char exactly overlaying the object.
fwrite() wrote:For each object, size calls shall be made to the fputc() function, taking the values (in order) from an array of unsigned char exactly overlaying the object.

Re: Debugging binutils under my OS?

Posted: Wed Oct 14, 2015 4:20 am
by mariuszp
So fread() and fwrite() are equivalent to calling read() and write() with (count*size) and the buffer passed (which is what they do in my case except fread() also calls fflush() first).

My fprintf() uses fwrite() internally and fscanf() calls fgetc() a lot. I just fixed my (f)scanf() implementation and that works as far as I cna tell. Time to get on with fprintf() because it's stupid and doesn't support qualifiers like %ld, just the single specifiers like "%d", "%s" etc and if as you say it is called a lot, that could indeed be the problem.

Re: Debugging binutils under my OS?

Posted: Wed Oct 14, 2015 4:25 am
by gerryg400
mariuszp wrote:So fread() and fwrite() are equivalent to calling read() and write() with (count*size) and the buffer passed (which is what they do in my case except fread() also calls fflush() first).
No, for example if you call ungetc() then the next fread() will get that character. Calling flush() first in wrong because that will forget the ungot chars.
mariuszp wrote:My fprintf() uses fwrite() internally and fscanf() calls fgetc() a lot. I just fixed my (f)scanf() implementation and that works as far as I cna tell. Time to get on with fprintf() because it's stupid and doesn't support qualifiers like %ld, just the single specifiers like "%d", "%s" etc and if as you say it is called a lot, that could indeed be the problem.
All the I/O methods must be built on the basic fgetc() and fputc() methods. You will need fprintf and fscanf of %08x etc. to work properly.

Re: Debugging binutils under my OS?

Posted: Wed Oct 14, 2015 4:29 am
by mariuszp
gerryg400 wrote:
mariuszp wrote:So fread() and fwrite() are equivalent to calling read() and write() with (count*size) and the buffer passed (which is what they do in my case except fread() also calls fflush() first).
No, for example if you call ungetc() then the next fread() will get that character. Calling flush() first in wrong because that will forget the ungot chars.
mariuszp wrote:My fprintf() uses fwrite() internally and fscanf() calls fgetc() a lot. I just fixed my (f)scanf() implementation and that works as far as I cna tell. Time to get on with fprintf() because it's stupid and doesn't support qualifiers like %ld, just the single specifiers like "%d", "%s" etc and if as you say it is called a lot, that could indeed be the problem.
All the I/O methods must be built on the basic fgetc() and fputc() methods. You will need fprintf and fscanf of %08x etc. to work properly.
Oh wait, I did handle the ungetc() case in fread() by the equivalent "if (fp->_ungot != -1) {*put++ = (char) fp->_ingot; size--};" but I forgot that I call fflush() first thus making it useless. I guess I should just implement it with fgetc() and fputc().

Also, why does ld need "%08x" in printf? (out of curiosity). I mean it reads/writes binary files.