www.delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp/1997/07/09/22:56:33

Date: Thu, 10 Jul 1997 14:54:35 +0000
From: Bill Currie <billc AT blackmagic DOT tait DOT co DOT nz>
Subject: Re: ctor ?
To: Andrew Crabtree <andrewc AT typhoon DOT rose DOT hp DOT com>
Cc: djgpp AT delorie DOT com
Reply-to: billc AT blackmagic DOT tait DOT co DOT nz
Message-id: <33C4F7AB.248E@blackmagic.tait.co.nz>
Organization: Tait Electronics NZ
MIME-version: 1.0
References: <199707100209 DOT AA214490589 AT typhoon DOT rose DOT hp DOT com>

Andrew Crabtree wrote:
> 
> 
>  Hello -
> 
>  Could someone explain how the .ctor section works for DJGPP
>  and if it actually works OK?

I'll try (and it DOES work correctly).

> 
>  I can see from the linker script /lib/djgpp.djl that
>  it appears to expect (or allow) a .ctor section to be present in the coff
>  file and that it does move it into the djgpp_ctor section.  However,
>  it can't get it to (or tell if it is) work properly.
> 
>  If I compile the following code
> 
>  #include <stdio.h>
>  int f()
>  {
>  return 5;
>  }
> 
>  int x = f();
> 
>  main()
>  {
>  printf("x = %d\n",x);
>  return 0;
>  }
> 
>  As C the compiler complains that it is using a non-constant initializer.
>  First I'm not sure if this is right.  I believe (2nd hand reference),
>  that this works with linux gcc.  I wouldn't normally code something that
>  like, just to test ctor.
> 
>  But if I use the c++ parser then I do get a
> 
>  __GLOBAL_$I$f__Fv
> 
>  function defined with proper code and a corresponding
> 
>  .section .ctor
>  .long __GLOBAL_$I$f__Fv
> 
>  At the end of the assembly file.

Yup, this all makes sense.  To do it in C, you need to do:

int x;

static void __attribute__((constructor)) set_x(void)
{
    x=f();
}

This will place a pointer to set_x into the .ctor section of the object
file.


>  My tests by running the executable and looking at the results (x = 0)
>  and by loading into gdb and trying to break on the function (never broke)
>  seem to indicate that the ctor is not being called.

It should be working for C++ (I've never had any problems).  But I have
no idea what gcc does with what you were doing in C.

What happens with .ctor is: gcc places a pointer to either a generated
functions (C++) or a user supplied function using
__attribute__((constructor)) (C) into the .ctor section of the .o file.
In C++, a function declared with __attribute__((constructor)) gets
called by the function generated by gcc.  When linking, all the .ctor
sections get concatenated into an array starting at djgpp_first_ctor and
ending just befor djgpp_last_ctor (via the linker script).  At startup,
the libc startup code (_main() in _main.c) goes through this array
calling each function in turn.  This happens before main is called
(actually, gcc places a call to _main() at the beginning of main(), but
libc calls _main itself (don't know why (dj, can you say why?)) and so
_main() also has a test to see if it has done the .ctor calls yet).

As to why you can't break on f(), I don't know.  If it was with the C
code, maybe it's due to the error/warning message you got.  For C++, all
I can think of is you have to place a breakpoint on the function before
ANY code is run.  Does gdb run all code up to main() on startup?

Also, it's a very similar story for .dtor (but the code for calling the
functions is somewhere in exit(), which (for the proponents of void
main()) gets called immediatly after main returns with main's return
value) but you use `__attribute__((destructor))' to create a .dtor
entry.

The order of .ctor and .dtor function calls is determined by the link
order of the .o files they are in.  I have no idea wheter .dtor calls
are in the reverse order of .ctor calls or not.

Bill
-- 
Leave others their otherness.

- Raw text -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019