Building my own 'freestanding' start-up and library - Unix

This is a discussion on Building my own 'freestanding' start-up and library - Unix ; I've been working on building my own toolchain running on Linux. I'm currently building a 'freestanding' library along with startup code to be linked together. Unfortunately I've run into problems with the startup code with passing command line arguments to ...

+ Reply to Thread
Results 1 to 15 of 15

Thread: Building my own 'freestanding' start-up and library

  1. Building my own 'freestanding' start-up and library

    I've been working on building my own toolchain running on Linux. I'm
    currently building a 'freestanding' library along with startup code to
    be linked together. Unfortunately I've run into problems with the
    startup code with passing command line arguments to main(). Whilst it
    works on most occasions, one of my test programs core dumps and
    debugging can't find the cause. Is this the correct newsgroup to get
    help? I use NASM and GCC to build the libraries and start-up code.

    Thanks
    --
    http://www.munted.org.uk

    Fearsome grindings.


  2. Re: Building my own 'freestanding' start-up and library

    Alex Buell writes:

    > I've been working on building my own toolchain running on Linux. I'm
    > currently building a 'freestanding' library along with startup code to
    > be linked together. Unfortunately I've run into problems with the
    > startup code with passing command line arguments to main(). Whilst it
    > works on most occasions, one of my test programs core dumps and
    > debugging can't find the cause. Is this the correct newsgroup to get
    > help? I use NASM and GCC to build the libraries and start-up code.


    Hi Alex,

    Back in comp.lang.c I suggested comp.os.linux.development.apps. But
    what the heck. Can you post the code in question, or a link to it?

  3. Re: Building my own 'freestanding' start-up and library

    On Mon, 20 Oct 2008 03:07:46 -0700, I waved a wand and this message
    magically appears in front of Nate Eldredge:

    > > I've been working on building my own toolchain running on Linux. I'm
    > > currently building a 'freestanding' library along with startup code
    > > to be linked together. Unfortunately I've run into problems with the
    > > startup code with passing command line arguments to main(). Whilst
    > > it works on most occasions, one of my test programs core dumps and
    > > debugging can't find the cause. Is this the correct newsgroup to get
    > > help? I use NASM and GCC to build the libraries and start-up
    > > code.

    >
    > Back in comp.lang.c I suggested comp.os.linux.development.apps. But
    > what the heck. Can you post the code in question, or a link to it?


    Your post hasn't turned up in comp.lang.c yet! I'll post my start-up
    code (it's in NASM and quite short), and we'll take it from there:

    section .data

    result dd 0

    params dd 0

    __argc dd 0
    __argv dd 0

    section .text
    extern main

    extern __init
    extern __exit

    global _start
    _start:
    nop ; debugger
    nop

    push ebp
    mov ebp, esp

    lea eax, [ebp + 4]
    mov [params], eax

    mov eax, [params]
    mov eax, [eax]
    mov [__argc], eax

    mov eax, [params]
    add eax, 4
    mov [__argv], eax

    call __init ; startup

    mov eax, [__argv]
    push eax ; push argv onto the stack

    mov eax, [__argc] ; push argc onto the stack
    push eax

    call main ; need to pass result code back to operating system
    mov [result], eax ; save result code

    pop eax ; pop argc off the stack
    pop eax ; pop argv off the stack

    pop ebp ; pop ebp off the stack

    call __exit ; cleanup

    mov ebx, [result]
    mov eax, 1
    int 0x80

    --
    http://www.munted.org.uk

    Fearsome grindings.


  4. Re: Building my own 'freestanding' start-up and library

    On Oct 20, 11:37*am, Alex Buell wrote:
    > On Mon, 20 Oct 2008 03:07:46 -0700, I waved a wand and this message
    > magically appears in front of Nate Eldredge:
    >
    > > > I've been working on building my own toolchain running on Linux. I'm
    > > > currently building a 'freestanding' library along with startup code
    > > > to be linked together. Unfortunately I've run into problems with the
    > > > startup code with passing command line arguments to main(). Whilst
    > > > it works on most occasions, one of my test programs core dumps and
    > > > debugging can't find the cause. Is this the correct newsgroup to get
    > > > help? I use NASM and GCC to build the libraries and start-up
    > > > code. * *

    >
    > > Back in comp.lang.c I suggested comp.os.linux.development.apps. *But
    > > what the heck. *Can you post the code in question, or a link to it?

    >
    > Your post hasn't turned up in comp.lang.c yet! I'll post my start-up
    > code (it's in NASM and quite short), and we'll take it from there:
    >
    > section .data
    >
    > * * * * result *dd * * *0
    >
    > * * * * params *dd * * *0
    >
    > * * * * __argc *dd * * *0
    > * * * * __argv *dd * * *0
    >
    > section .text
    > * * * * extern main
    >
    > * * * * extern *__init
    > * * * * extern *__exit
    >
    > * * * * global *_start
    > _start:
    > * * * * nop * * * * * * * * * * ; debugger
    > * * * * nop
    >
    > * * * * push * *ebp
    > * * * * mov * * ebp, esp
    >
    > * * * * lea * * eax, [ebp + 4]
    > * * * * mov * * [params], eax
    >
    > * * * * mov * * eax, [params]
    > * * * * mov * * eax, [eax]
    > * * * * mov * * [__argc], eax
    >
    > * * * * mov * * eax, [params]
    > * * * * add * * eax, 4


    missing line:
    mov eax, [eax]

    > * * * * mov * * [__argv], eax
    >
    > * * * * call * *__init * * * * *; startup
    >
    > * * * * mov * * eax, [__argv]
    > * * * * push * *eax * * * * * * ; push argv onto the stack
    >
    > * * * * mov * * eax, [__argc] * ; push argc onto the stack
    > * * * * push * *eax
    >
    > * * * * call * *main * * * * * *; need to pass result code back to operating system
    > * * * * mov * * [result], eax * ; save result code
    >
    > * * * * pop * * eax * * * * * * ; pop argc off the stack
    > * * * * pop * * eax * * * * * * ; pop argv off the stack
    >
    > * * * * pop * * ebp * * * * * * ; pop ebp off thestack
    >
    > * * * * call * *__exit * * * * *; cleanup
    >
    > * * * * mov * * ebx, [result]
    > * * * * mov * * eax, 1
    > * * * * int * * 0x80


    Please note, that main() function may expect three arguments:

    int main (int argc, char *argv[], char *env[])

    http://www.opengroup.org/onlinepubs/...ions/exec.html


    Applications that do not require to access their arguments may use the
    form:

    main(void)

    as specified in the ISO C standard. However, the implementation will
    always provide the two arguments argc and argv, even if they are not
    used.

    Some implementations provide a third argument to main() called envp.
    This is defined as a pointer to the environment. The ISO C standard
    specifies invoking main() with two arguments, so implementations must
    support applications written this way. Since this volume of IEEE Std
    1003.1-2001 defines the global variable environ, which is also
    provided by historical implementations and can be used anywhere that
    envp could be used, there is no functional need for the envp argument.
    Applications should use the getenv() function rather than accessing
    the environment directly via either envp or environ. Implementations
    are required to support the two-argument calling sequence, but this
    does not prohibit an implementation from supporting envp as an
    optional third argument.


    --
    Max

  5. Re: Building my own 'freestanding' start-up and library

    On Mon, 20 Oct 2008 08:52:42 -0700 (PDT), I waved a wand and this
    message magically appears in front of Maxim Yegorushkin:

    > > * * * * mov * * eax, [params]
    > > * * * * add * * eax, 4

    >
    > missing line:
    > mov eax, [eax]


    No, if I do that, that actually gets the *value* instead of the
    address pointing to *argv[].

    > Please note, that main() function may expect three arguments:
    >
    > int main (int argc, char *argv[], char *env[])
    >
    > http://www.opengroup.org/onlinepubs/...ions/exec.html


    Yes, I'm aware of that. I have plans to add that at some point in the
    future once I resolve my coredump problems. One of my test programs
    coredumps, but the other two test programs doesn't, which is why this
    has completely stumped me!

    Thanks,
    Alex
    --
    http://www.munted.org.uk

    Fearsome grindings.


  6. Re: Building my own 'freestanding' start-up and library

    Alex Buell writes:

    > On Mon, 20 Oct 2008 03:07:46 -0700, I waved a wand and this message
    > magically appears in front of Nate Eldredge:
    >
    >> > I've been working on building my own toolchain running on Linux. I'm
    >> > currently building a 'freestanding' library along with startup code
    >> > to be linked together. Unfortunately I've run into problems with the
    >> > startup code with passing command line arguments to main(). Whilst
    >> > it works on most occasions, one of my test programs core dumps and
    >> > debugging can't find the cause. Is this the correct newsgroup to get
    >> > help? I use NASM and GCC to build the libraries and start-up
    >> > code.

    >>
    >> Back in comp.lang.c I suggested comp.os.linux.development.apps. But
    >> what the heck. Can you post the code in question, or a link to it?

    >
    > Your post hasn't turned up in comp.lang.c yet! I'll post my start-up
    > code (it's in NASM and quite short), and we'll take it from there:


    [code snipped]

    That code looks reasonable to me. The only deficit is that it doesn't
    get the environment variables to pass to main() as a third argument, or
    to set the global variable `environ'. But if you aren't using
    environment variables that's not relevant.

    Can you post the code for the test program that crashes?

  7. Re: Building my own 'freestanding' start-up and library

    On Mon, 20 Oct 2008 11:00:17 +0100 Alex Buell wrote:

    | I've been working on building my own toolchain running on Linux. I'm
    | currently building a 'freestanding' library along with startup code to
    | be linked together. Unfortunately I've run into problems with the
    | startup code with passing command line arguments to main(). Whilst it
    | works on most occasions, one of my test programs core dumps and
    | debugging can't find the cause. Is this the correct newsgroup to get
    | help? I use NASM and GCC to build the libraries and start-up code.

    Will this be FOSS? I'm curious if it will be smaller than klibc. I'd have
    an interest in the results either way.

    --
    |WARNING: Due to extreme spam, googlegroups.com is blocked. Due to ignorance |
    | by the abuse department, bellsouth.net is blocked. If you post to |
    | Usenet from these places, find another Usenet provider ASAP. |
    | Phil Howard KA9WGN (email for humans: first name in lower case at ipal.net) |

  8. Re: Building my own 'freestanding' start-up and library

    On Mon, 20 Oct 2008 11:05:58 -0700, I waved a wand and this message
    magically appears in front of Nate Eldredge:

    > Alex Buell writes:
    >
    > > On Mon, 20 Oct 2008 03:07:46 -0700, I waved a wand and this message
    > > magically appears in front of Nate Eldredge:
    > >
    > >> > I've been working on building my own toolchain running on Linux.
    > >> > I'm currently building a 'freestanding' library along with
    > >> > startup code to be linked together. Unfortunately I've run into
    > >> > problems with the startup code with passing command line
    > >> > arguments to main(). Whilst it works on most occasions, one of
    > >> > my test programs core dumps and debugging can't find the cause.
    > >> > Is this the correct newsgroup to get help? I use NASM and GCC to
    > >> > build the libraries and start-up code.
    > >>
    > >> Back in comp.lang.c I suggested comp.os.linux.development.apps.
    > >> But what the heck. Can you post the code in question, or a link
    > >> to it?

    > >
    > > Your post hasn't turned up in comp.lang.c yet! I'll post my start-up
    > > code (it's in NASM and quite short), and we'll take it from there:

    >
    > [code snipped]
    >
    > That code looks reasonable to me. The only deficit is that it doesn't
    > get the environment variables to pass to main() as a third argument,
    > or to set the global variable `environ'. But if you aren't using
    > environment variables that's not relevant.
    >
    > Can you post the code for the test program that crashes?


    #include

    int main(int argc, char *argv[])
    {
    printf("Testing..\n\n");
    printf("argc = %d\n", argc);
    printf("argv[0] = %s\n", argv[0]);

    return 0;
    }

    This works perfectly well with GCC and glibc. When rebuilt and linked
    against my start-up code and my library, it coredumps on the printing
    of argc's value:

    ./main
    Testing..

    Segmentation fault

    This is what I see with gdb:
    main (argc=Cannot access memory at address 0x1 ) at main.c:6
    6 printf("argc = %d\n", argc);
    (gdb) bt
    #0 main (argc=Cannot access memory at address 0x1
    ) at main.c:6

    But the very strange thing is that my other program that deals with argc
    and argv works perfectly!
    --
    http://www.munted.org.uk

    Fearsome grindings.


  9. Re: Building my own 'freestanding' start-up and library

    On 20 Oct 2008 19:00:48 GMT, I waved a wand and this message magically
    appears in front of phil-news-nospam@ipal.net:

    > | I've been working on building my own toolchain running on Linux. I'm
    > | currently building a 'freestanding' library along with startup code
    > to | be linked together. Unfortunately I've run into problems with the
    > | startup code with passing command line arguments to main(). Whilst
    > it | works on most occasions, one of my test programs core dumps and
    > | debugging can't find the cause. Is this the correct newsgroup to get
    > | help? I use NASM and GCC to build the libraries and start-up code.
    >
    > Will this be FOSS? I'm curious if it will be smaller than klibc.
    > I'd have an interest in the results either way.


    Oh yes, it definitely would be an open source project. At the moment
    it's purely to help me learn about this sort of thing.
    --
    http://www.munted.org.uk

    Fearsome grindings.


  10. Re: Building my own 'freestanding' start-up and library

    Alex Buell writes:

    > On Mon, 20 Oct 2008 11:05:58 -0700, I waved a wand and this message
    > magically appears in front of Nate Eldredge:
    >>
    >> Can you post the code for the test program that crashes?

    >
    > #include
    >
    > int main(int argc, char *argv[])
    > {
    > printf("Testing..\n\n");
    > printf("argc = %d\n", argc);
    > printf("argv[0] = %s\n", argv[0]);
    >
    > return 0;
    > }


    Looks fine. I can't test it, of course, because I can't link with glibc
    for obvious reasons, and I don't have your printf().

    > This works perfectly well with GCC and glibc. When rebuilt and linked
    > against my start-up code and my library, it coredumps on the printing
    > of argc's value:
    >
    > ./main
    > Testing..
    >
    > Segmentation fault
    >
    > This is what I see with gdb:
    > main (argc=Cannot access memory at address 0x1 ) at main.c:6
    > 6 printf("argc = %d\n", argc);
    > (gdb) bt
    > #0 main (argc=Cannot access memory at address 0x1
    > ) at main.c:6


    I think the "Cannot access memory" message might be a gdb bug, since it
    doesn't make any sense in this context.

    > But the very strange thing is that my other program that deals with argc
    > and argv works perfectly!


    Yeah, I'm inclined to think the bug is somewhere else.

    Some ideas:

    - Try single-stepping the program one instruction at a time (using gdb's
    "si" command; "display /i $pc" is also useful) until it crashes. This
    might help figure out exactly where the problem lies.

    - Post a link to the complete library code, everything needed to build
    the binary you made, and the commands to do it. gcc, gdb and kernel
    versions might also be useful information.

    - Post a link to your unstripped binary which exhibits the problem.

  11. Re: Building my own 'freestanding' start-up and library

    On Mon, 20 Oct 2008 12:48:40 -0700, I waved a wand and this message
    magically appears in front of Nate Eldredge:

    > Yeah, I'm inclined to think the bug is somewhere else.
    >
    > Some ideas:
    >
    > - Try single-stepping the program one instruction at a time (using
    > gdb's "si" command; "display /i $pc" is also useful) until it
    > crashes. This might help figure out exactly where the problem lies.
    >
    > - Post a link to the complete library code, everything needed to build
    > the binary you made, and the commands to do it. gcc, gdb and kernel
    > versions might also be useful information.
    >
    > - Post a link to your unstripped binary which exhibits the problem.


    I'll do even better than that, I'll tar up my sources and put it here
    for download: http://www.munted.org.uk/programming/bcc.tar.gz

    To build everything you'll need the GNU toolchain and Linux, just type
    make in the root directory. You'l find the test programs in the
    lib/linux subdirectory.

    Regards,
    Alex
    --
    http://www.munted.org.uk

    Fearsome grindings.


  12. Re: Building my own 'freestanding' start-up and library

    Alex Buell writes:

    > On Mon, 20 Oct 2008 12:48:40 -0700, I waved a wand and this message
    > magically appears in front of Nate Eldredge:
    >
    >> Yeah, I'm inclined to think the bug is somewhere else.
    >>
    >> Some ideas:
    >>
    >> - Try single-stepping the program one instruction at a time (using
    >> gdb's "si" command; "display /i $pc" is also useful) until it
    >> crashes. This might help figure out exactly where the problem lies.
    >>
    >> - Post a link to the complete library code, everything needed to build
    >> the binary you made, and the commands to do it. gcc, gdb and kernel
    >> versions might also be useful information.
    >>
    >> - Post a link to your unstripped binary which exhibits the problem.

    >
    > I'll do even better than that, I'll tar up my sources and put it here
    > for download: http://www.munted.org.uk/programming/bcc.tar.gz
    >
    > To build everything you'll need the GNU toolchain and Linux, just type
    > make in the root directory. You'l find the test programs in the
    > lib/linux subdirectory.


    Ok, here's the problem.

    The bug is actually in __write. Functions called from C are required to
    preserve the contents of the ebx register (also esi and edi), and
    __write doesn't.

    It happens that main was storing the address of argc in the ebx register
    during the first call to printf. __write filled in ebx with 1, the file
    descriptor of stdout, and apparently none of the other functions were
    using ebx. So when printf returned, ebx had the value 1, and main's
    attempt to fetch the value of argc from that address caused the
    segfault.

    Incidentally, this also explains the weird "argc=Cannot access memory at
    address 0x1" message from gdb: the debugger also knew that ebx was
    supposed to contain the address of argc. I hadn't realized the
    debugging information could express that sort of thing. (It appears
    that gcc generates code in main() to align the stack, which makes its
    handling of local variables a bit trickier than just offsets from ebp.)

    For future reference, gcc on i386 uses the SYSV ABI for its calling
    conventions. I found a copy online at
    http://www.stanford.edu/class/cs140/...abi-i386-4.pdf
    ; see pages 3-1 through 3-19. Disregard the stuff about "Operating
    system interface" as it doesn't apply to Linux.

    Neat project, I think this sort of thing can be extremely educational,
    not to mention useful.

  13. Re: Building my own 'freestanding' start-up and library

    On Mon, 20 Oct 2008 15:20:43 -0700, I waved a wand and this message
    magically appears in front of Nate Eldredge:

    > > To build everything you'll need the GNU toolchain and Linux, just
    > > type make in the root directory. You'l find the test programs in the
    > > lib/linux subdirectory.

    >
    > Ok, here's the problem.
    >
    > The bug is actually in __write. Functions called from C are required
    > to preserve the contents of the ebx register (also esi and edi), and
    > __write doesn't.
    >
    > It happens that main was storing the address of argc in the ebx
    > register during the first call to printf. __write filled in ebx with
    > 1, the file descriptor of stdout, and apparently none of the other
    > functions were using ebx. So when printf returned, ebx had the value
    > 1, and main's attempt to fetch the value of argc from that address
    > caused the segfault.


    Botheration, I hadn't thought to debug __write! Thank you very much for
    taking the trouble to track down the problem for me, it's much
    appreciated.

    > Incidentally, this also explains the weird "argc=Cannot access memory
    > at address 0x1" message from gdb: the debugger also knew that ebx was
    > supposed to contain the address of argc. I hadn't realized the
    > debugging information could express that sort of thing. (It appears
    > that gcc generates code in main() to align the stack, which makes its
    > handling of local variables a bit trickier than just offsets from
    > ebp.)


    Obviously I need to disable this behaviour in GCC, thanks once again.

    > For future reference, gcc on i386 uses the SYSV ABI for its calling
    > conventions. I found a copy online at
    > http://www.stanford.edu/class/cs140/...abi-i386-4.pdf
    > ; see pages 3-1 through 3-19. Disregard the stuff about "Operating
    > system interface" as it doesn't apply to Linux.
    >
    > Neat project, I think this sort of thing can be extremely educational,
    > not to mention useful.


    Agreed, that's why I've been working on this in my spare time. Once
    again, thanks I'm quite grateful.
    --
    http://www.munted.org.uk

    Fearsome grindings.


  14. Re: Building my own 'freestanding' start-up and library

    Alex Buell writes:

    > On Mon, 20 Oct 2008 15:20:43 -0700, I waved a wand and this message
    > magically appears in front of Nate Eldredge:
    >
    >> > To build everything you'll need the GNU toolchain and Linux, just
    >> > type make in the root directory. You'l find the test programs in the
    >> > lib/linux subdirectory.

    >>
    >> Ok, here's the problem.
    >>
    >> The bug is actually in __write. Functions called from C are required
    >> to preserve the contents of the ebx register (also esi and edi), and
    >> __write doesn't.
    >>
    >> It happens that main was storing the address of argc in the ebx
    >> register during the first call to printf. __write filled in ebx with
    >> 1, the file descriptor of stdout, and apparently none of the other
    >> functions were using ebx. So when printf returned, ebx had the value
    >> 1, and main's attempt to fetch the value of argc from that address
    >> caused the segfault.

    >
    > Botheration, I hadn't thought to debug __write! Thank you very much for
    > taking the trouble to track down the problem for me, it's much
    > appreciated.


    No problem, it was interesting.

    >> Incidentally, this also explains the weird "argc=Cannot access memory
    >> at address 0x1" message from gdb: the debugger also knew that ebx was
    >> supposed to contain the address of argc. I hadn't realized the
    >> debugging information could express that sort of thing. (It appears
    >> that gcc generates code in main() to align the stack, which makes its
    >> handling of local variables a bit trickier than just offsets from
    >> ebp.)

    >
    > Obviously I need to disable this behaviour in GCC, thanks once again.


    Why? I don't see how it can cause a problem, and it may help in terms
    of performance.

  15. Re: Building my own 'freestanding' start-up and library

    On Tue, 21 Oct 2008 11:19:46 -0700, I waved a wand and this message
    magically appears in front of Nate Eldredge:

    > > Botheration, I hadn't thought to debug __write! Thank you very much
    > > for taking the trouble to track down the problem for me, it's much
    > > appreciated.

    >
    > No problem, it was interesting.


    I fixed it this morning; once I knew that it was clobbering ebx, by
    adding some prologue and epilogue code, and I also realised that if
    you push more values onto the stack, you need to add the number of
    bytes so you can access the variables that has also been pushed onto
    the stack by the caller. It's quite fundamental and I had neglected to
    take this into account!

    > > Obviously I need to disable this behaviour in GCC, thanks once
    > > again.

    >
    > Why? I don't see how it can cause a problem, and it may help in terms
    > of performance.


    No matter, I realised after this that I wouldn't need to.

    Thanks
    --
    http://www.munted.org.uk

    Fearsome grindings.


+ Reply to Thread