4

With the following CFLAGS:

-Wall -Werror -Wextra -pedantic -std=c99 -O3 -nostartfiles -nodefaultlibs

my __start entry point (notice -nostartfiles) is successfully compiled and put into an output executable.

However, when I add -flto flag, both the entry point and functions called by it only are optimized out. Moreover, the following linking is performed with neither error nor warning, but with incorrect (random) entry point.

A question is how to prevent __start function from being optimized out. It`s also interesting for me why a linker “forgets” about an external dependency on my entry point in lack of the default one.

My GCC version is gcc (i686-posix-dwarf-rev1, Built by MinGW-W64 project) 4.9.2.


UPD:

Source code (fixed with help of @FUZxxl, who wrote about prepended underscores in Windows ABI):

#include <windows.h>

void _start()
{
    MessageBox(NULL, TEXT("Hello world."), TEXT(""), MB_OK);
    ExitProcess(0);
}

Assembly output emitted by a linker (-S):

  1. Non--flto version:

    Disassembly of section .text:
    
    00401000 <__start>:
      401000:       83 ec 1c                sub    $0x1c,%esp
      401003:       c7 44 24 0c 00 00 00    movl   $0x0,0xc(%esp)
      40100a:       00
      40100b:       c7 44 24 08 00 20 40    movl   $0x402000,0x8(%esp)
      401012:       00
      401013:       c7 44 24 04 0d 20 40    movl   $0x40200d,0x4(%esp)
      40101a:       00
      40101b:       c7 04 24 00 00 00 00    movl   $0x0,(%esp)
      401022:       ff 15 54 40 40 00       call   *0x404054
      401028:       83 ec 10                sub    $0x10,%esp
      40102b:       c7 04 24 00 00 00 00    movl   $0x0,(%esp)
      401032:       ff 15 4c 40 40 00       call   *0x40404c
      401038:       90                      nop
      401039:       90                      nop
      40103a:       90                      nop
      40103b:       90                      nop
      40103c:       90                      nop
      40103d:       90                      nop
      40103e:       90                      nop
      40103f:       90                      nop
    
    00401040 <__CTOR_LIST__>:
      401040:       ff                      (bad)
      401041:       ff                      (bad)
      401042:       ff                      (bad)
      401043:       ff 00                   incl   (%eax)
      401045:       00 00                   add    %al,(%eax)
            ...
    
    00401048 <__DTOR_LIST__>:
      401048:       ff                      (bad)
      401049:       ff                      (bad)
      40104a:       ff                      (bad)
      40104b:       ff 00                   incl   (%eax)
      40104d:       00 00                   add    %al,(%eax)
    
  2. -flto version (notice the lack of _start here, just a bunch of thunks for API entries):

    Disassembly of section .text:
    
    00401000 <_ExitProcess@4>:
      401000:       ff 25 4c 30 40 00       jmp    *0x40304c
      401006:       90                      nop
      401007:       90                      nop
    
    00401008 <_MessageBoxA@16>:
      401008:       ff 25 54 30 40 00       jmp    *0x403054
      40100e:       90                      nop
      40100f:       90                      nop
    
    00401010 <__CTOR_LIST__>:
      401010:       ff                      (bad)
      401011:       ff                      (bad)
      401012:       ff                      (bad)
      401013:       ff 00                   incl   (%eax)
      401015:       00 00                   add    %al,(%eax)
            ...
    
    00401018 <__DTOR_LIST__>:
      401018:       ff                      (bad)
      401019:       ff                      (bad)
      40101a:       ff                      (bad)
      40101b:       ff 00                   incl   (%eax)
      40101d:       00 00                   add    %al,(%eax)
    
Community
  • 1
  • 1
Arhadthedev
  • 219
  • 1
  • 7
  • 19

1 Answers1

3

With all the exotic/embedded-related options you've set, you have to ensure that your symbol is seen as your entrypoint and not garbage collected by linker optimizations (--gc-sections also does that: collecting "useless" sections)

You can end up with a fully empty .elf file since no section is reachable.

To tell the linker that you are using that symbol as an entrypoint (and avoid that the linker eludes it!), just add

-Wl,-e__start

option to your link command (or write a linker spec file where you declare your symbol, but the command line option is easier)

Jean-François Fabre
  • 137,073
  • 23
  • 153
  • 219