Page 1 of 2

printf() problem with ported NewLib

Posted: Thu Apr 25, 2013 2:49 pm
by IanSeyler
I'm wondering if anyone else has seen this behavior.

Example:

Code: Select all

printf("NewLib Test Application\n=======================\n");
printf("%s %d\n", "Output:", 1234);
Result:

Code: Select all

NewLib Test Application
Output: 1234
The NewLib write() function was only called to print 24 characters on the first call to printf().

Re: printf() problem with ported NewLib

Posted: Thu Apr 25, 2013 3:05 pm
by Kazinsal
I would wager it's because of the newline and not an arbitrary 24-character limit. Try removing the newline?

Re: printf() problem with ported NewLib

Posted: Fri Apr 26, 2013 8:56 am
by IanSeyler
Code:

Code: Select all

printf("NewLib Test Application=======================\n");
printf("%s %d\n", "Output:", 1234);
Results:

Code: Select all

NewLib Test Application=======================
Output: 1234
Looks like it stops printing after the first newline. That first call to printf() should result with one call to write(), correct?

Re: printf() problem with ported NewLib

Posted: Fri Apr 26, 2013 9:59 am
by Kazinsal
My crystal ball tells me you haven't implemented isatty() and/or fstat(), so newlib is confused as to what buffering to use.

Re: printf() problem with ported NewLib

Posted: Fri Apr 26, 2013 10:01 am
by Antti
Does your write() correctly handle the newline?

Re: printf() problem with ported NewLib

Posted: Fri Apr 26, 2013 12:13 pm
by bluemoon
ReturnInfinity wrote:Looks like it stops printing after the first newline. That first call to printf() should result with one call to write(), correct?
In my implementation, newlib make 2 calls to write with if there is line feed in middle of string:

Code: Select all

printf ("  PID[%d]: Hello again! counter=%d, foo=%d\n   line2\n", pid, i, g_foo.foo++);


Result:
SYSCALL : fstat(1, 7FBFF7D0)
SYSCALL : sbrk(00000430)
SYSCALL : sbrk(00000BD0)
SYSCALL : write(1, 01000010, 20)
FOO::FOO(0x10d008);
SYSCALL : write(1, 01000010, 21)
FOO::FOO(0x1000420);
SYSCALL : getpid() -> FFFFFFFF:801210D0: 1
SYSCALL : write(1, 01000010, 42)
  PID[1]: Hello again! counter=0, foo=123
SYSCALL : write(1, 01000010, 9)
   line2
SYSCALL : usleep(000F4240)
My fstat:

Code: Select all

long kservice_fstat(int fd, struct stat* st) {
    kprintf ( "SYSCALL : fstat(%d, %p)\n", fd, st);
    if ( st == NULL ) return -1;
    st->st_mode = S_IFCHR; // | S_IWUSR;
                           //    st->st_blksize = 1;
    return 0;
}                   

Re: printf() problem with ported NewLib

Posted: Fri Apr 26, 2013 12:40 pm
by IanSeyler
Blacklight, isatty() looks fine.. it was just returning 1 be default. I changed it to return 1 for STDOUT and STDERR. fstat was just set to minimal implementation of returning 0. I'll take a further look at fstat().

Antti, write() handles the newlines correctly. write(1, "test1\ntest2\n", 12) works as expected.

Re: printf() problem with ported NewLib

Posted: Fri Apr 26, 2013 1:35 pm
by IanSeyler
I think my issue is with sbrk(). A really simple program crashes whereas a more complicated one doesn't.

I get a page-fault with this:

Code: Select all

#include <stdio.h>

int main()
{
    printf("Hello1\nHello2\nHello3\n");
    return 0;
}
I'll do some digging and report back.

Re: printf() problem with ported NewLib

Posted: Mon Apr 29, 2013 2:46 pm
by IanSeyler
My sbrk() is borked (I think)! I'm also thinking it could be due to me not zeroing BSS.

Should I be implementing a crt0.c file to run before calling main?

Should NewLib work correctly with flat binaries?

My linker script:

Code: Select all

OUTPUT_FORMAT("binary")
OUTPUT_ARCH("i386:x86-64")
ENTRY(main)
SECTIONS
{
        . = 0x0000000000200000;
        .text : { *(.text) }
        .data : { *(.data .rodata) QUAD(ADDR(.bss)+SIZEOF(.bss)) }
        .bss : { *(.bss) }
        end = .; _end = .; __end = .;
}
How I compile:

Code: Select all

gcc -I ../../newlib-2.0.0/newlib/libc/include/ -c helloc.c -o helloc.o
ld -T app.ld -o helloc.app helloc.o libc.a
More debugging to do!

Re: printf() problem with ported NewLib

Posted: Mon Apr 29, 2013 4:25 pm
by Owen
ReturnInfinity wrote:I'm also thinking it could be due to me not zeroing BSS.
That is part of the contract for BSS...

Re: printf() problem with ported NewLib

Posted: Mon Apr 29, 2013 11:34 pm
by bluemoon
Owen wrote:
ReturnInfinity wrote:I'm also thinking it could be due to me not zeroing BSS.
That is part of the contract for BSS...
LOL, I saw at least 5 people on this forum, including myself, made this mistake :mrgreen:
I know, when you drag newlib into your OS you just can't wait to make some test application, and missed this (and other) critical parts.

Re: printf() problem with ported NewLib

Posted: Tue Apr 30, 2013 12:15 am
by sortie
If you don't already, you ought to be using a real cross-compiler to build your kernel and user-space. Please do that.

Re: printf() problem with ported NewLib

Posted: Tue Apr 30, 2013 2:40 am
by dozniak
bluemoon wrote:
Owen wrote:
ReturnInfinity wrote:I'm also thinking it could be due to me not zeroing BSS.
That is part of the contract for BSS...
LOL, I saw at least 5 people on this forum, including myself, made this mistake :mrgreen:
I know, when you drag newlib into your OS you just can't wait to make some test application, and missed this (and other) critical parts.
If you're using multiboot bootloader, it clears out the bss for you. In any other case - it's up to you.

Re: printf() problem with ported NewLib

Posted: Tue Apr 30, 2013 3:05 am
by bluemoon
dozniak wrote:If you're using multiboot bootloader, it clears out the bss for you. In any other case - it's up to you.
NewLib Test Application=======================
I presume we are dealing with loading application, not about loading the kernel from boot loader.

Re: printf() problem with ported NewLib

Posted: Tue Apr 30, 2013 5:24 am
by dozniak
bluemoon wrote:
dozniak wrote:If you're using multiboot bootloader, it clears out the bss for you. In any other case - it's up to you.
NewLib Test Application=======================
I presume we are dealing with loading application, not about loading the kernel from boot loader.
Oh, indeed. In this case the crt should deal with that.