<!DOCTYPE html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  </head>
  <body>
    <p>And for notice, I have disabled -CX and -XX</p>
    <div class="moz-cite-prefix">W dniu 22.07.2026 o 16:09, Dibo via
      fpc-pascal pisze:<br>
    </div>
    <blockquote type="cite"
      cite="mid:3328aa7b-c325-45f1-9684-8cddc45907f1@wp.pl">
      <meta http-equiv="content-type" content="text/html; charset=UTF-8">
      <p>Hi,</p>
      <p><span class="HwtZe" lang="en"><span class="jCAhz ChMk0b"><span
              class="ryNqvb">I suspect that my first message was blocked
              because I attached ODT document. Please ignore duplicate
              if it show up.</span></span></span></p>
      <p>I mentioned about this issue some time ago in the topic about
        PasFLTK bindings which I made. I decided to make dedicated
        thread because it seems to be interesting.</p>
      <p>So. I'm developing PasFLTK bindings for CFLTK which is flatten
        C binding for major FLTK UI framework written in C++. PasFLTK
        has two modes, shared library which work perfectly fine and
        experimental static linking.</p>
      <p>Static linking has issues which I'm <span class="HwtZe"
          lang="en"><span class="jCAhz ChMk0b"><span class="ryNqvb">consistently</span></span></span> fixing.
        Major problem is that C++ classes are not initialized in proper
        way. Problem is not a matter of "Static Initialization Order
        Fiasco" because CFLTK/FLTK is designed to be static linking for
        default (and that is how other language bindings are using it).
        Problem is how FPC LD linker prepare "startup" routines. For
        example:</p>
      <p>Class Fl_File_Chooser2.cxx has this public variable:</p>
      <p>const char      *Fl_File_Chooser::filesystems_label =
        Fl::system_driver()->filesystems_label();</p>
      <p>System_driver is not initialized yet so filesystems_label
        become null which result with access violations. Since I'm linux
        user I started from this platform, working on this with Claude
        AI (which amazed me how deeply he can analyze binaries on low
        level). On linux, fix was small and easy (for Claude, not for me
        of course). LD linker prepare wrong init structure and doesn't
        call the __init_array_start in linux ELF standard. So patch
        looks like that:<br>
        <br>
      </p>
      <p>type<br>
          TCtorProc = procedure(); cdecl;<br>
          PCtorProc = ^TCtorProc;<br>
        <br>
        var<br>
          __init_array_start: Byte; external name '__init_array_start';<br>
          __init_array_end: Byte; external name '__init_array_end';<br>
        <br>
        procedure RunCppGlobalConstructorsLinux;<br>
        var<br>
          p, pend: PCtorProc;<br>
        begin<br>
          p := PCtorProc(@__init_array_start);<br>
          pend := PCtorProc(@__init_array_end);<br>
          while p < pend do<br>
          begin<br>
            if Assigned(p^) then<br>
              p^();<br>
            Inc(p);<br>
          end;<br>
        end; <br>
        <br>
        That small piece of code fixed everything and static linking
        work like a charm on linux. I have project (which I publish
        soon) totally written as static linking and didn't notice any
        new issues so far.</p>
      <p>Now windows version. Here complication start. First, build-in
        FPC linker is useless and throw error:</p>
      <p>Error: Failed reading coff file, invalid section index while
        reading
        C:\Users\vboxuser\Documents\CFLTKlibs\libcfltk.a(cfl_window.cpp.obj)<br>
        <br>
        I had to use -Xe flag which switch to external ld.exe linker.
        But then I had DWARF errors because LD support only up to 4
        version and my MinGW toolchain (MSYS2 on windows) is using ver.
        5. I had to call `strip --strip-debug` on all *.a files
        (including some MinGW - e.g libstd++.a).</p>
      <p>Now, when binding are compiling fine, I fall to the same
        problem with initialization as on linux. I spent few evenings
        with Claude on this. We compared objdump -h and extracted
        objects on exactly the same demos written line by line one using
        C (CFLTK) and second Free Pascal. Since linux use ELF we get
        __init_array_start, on windows PE - it looks harder. LD.exe <span
          class="HwtZe" lang="en"><span class="jCAhz ChMk0b"><span
              class="ryNqvb">delivered with FPC is quite old and doesn't
              use modern standard. Demo written in C and linked by LD
              from toolchain has correct .ctors and __CTOR_LIST__ which
              FPC ld.exe is missing (in fact, filling it incorrectly).
              Tried using -FD"C:\msys64\mingw64\bin" which load ld.exe
              from MinGW toolchain but this result with dozens errors:</span></span></span></p>
      <p><span class="HwtZe" lang="en"><span class="jCAhz ChMk0b"><span
              class="ryNqvb">C:\msys64\mingw64\bin\ld.exe:
              C:\programowanie\lazarus\fpc\3.2.2\units\x86_64-win64\rtl\sysutils.o:
              illegal relocation type 0 at address 0<br>
              C:\msys64\mingw64\bin\ld.exe:
              C:\programowanie\lazarus\fpc\3.2.2\units\x86_64-win64\rtl\math.o:
              illegal relocation type 0 at address 0</span></span></span></p>
      <p><span class="HwtZe" lang="en"><span class="jCAhz ChMk0b"><span
              class="ryNqvb">Claude also compared rust bindings for
              CFLTK because it also use static linking. They had also
              problems and are stick to the specific toolchain. But
              there problem was easier to fix because Rust linker
              correctly linking crt2.o and has own guardians rsbegin.o
              and rsend.o (</span></span></span><span class="HwtZe"
          lang="en"><span class="jCAhz ChMk0b"><span class="ryNqvb">equivalent
              of </span></span></span>crtbegin.o and crtend.o) which are
        missing in FPC ld linker.</p>
      <p>Finally I get it working with Claude but this require
        reorganize *.a and C++ objects with --globalize-symbol and this
        solution is not acceptable for me because it require <span
          class="HwtZe" lang="en"><span class="jCAhz ChMk0b"><span
              class="ryNqvb">engagement everytime when something changed
              in CFLT/FLTK source or even in MinGW.</span></span></span></p>
      <p><span class="HwtZe" lang="en"><span class="jCAhz ChMk0b"><span
              class="ryNqvb">I'll be not writting anymore and just
              attach summary of our work which I asked Claude to write
              in short. It has more technical details. To sum up. Is
              there any plans to upgrade LD linker or exists any alpha /
              beta of upcoming release? </span></span></span><span
          class="HwtZe" lang="en"><span class="jCAhz ChMk0b"><span
              class="ryNqvb">The difference between FPC ld and GCC ld is
              almost 10 years. </span></span></span><span class="HwtZe"
          lang="en"><span class="jCAhz ChMk0b"><span class="ryNqvb">I
              read somewhere that FPC is not designed to link C++ (only
              C) but as we can see, it could be just small step to make
              it possible and that open huge door. </span></span></span></p>
      <p><span class="HwtZe" lang="en"><span class="jCAhz ChMk0b"><span
              class="ryNqvb">Below is Claude's summary.</span></span></span></p>
      <p><span class="HwtZe" lang="en"><span class="jCAhz ChMk0b"><span
              class="ryNqvb">Regards, Dibo.</span></span></span></p>
      <p><span class="HwtZe" lang="en"><span class="jCAhz ChMk0b"><span
              class="ryNqvb">Environment:<br>
              <br>
                  Free Pascal Compiler 3.2.2, Windows target
              x86_64-win64<br>
              <br>
                  Bundled linker:
              C:\programowanie\lazarus\fpc\3.2.2\bin\x86_64-win64\ld.exe
              — GNU ld (GNU Binutils) 2.28<br>
              <br>
                  Comparison linker: ld.exe from MSYS2
              mingw-w64-x86_64-binutils package, located at
              C:\msys64\mingw64\bin\ld.exe — GNU ld (GNU Binutils)
              2.46.1<br>
              <br>
                  GCC/G++ used to build FLTK, CFLTK, and the comparison
              C++ demo: 16.1.0 (MSYS2 mingw-w64-x86_64-gcc, reported as
              "GCC 16.1.0"<br>
              <br>
                  FLTK version: 1.4.5, CFLTK version: 1.5.23<br>
              <br>
              Root cause identified: FPC 3.2.2's bundled ld.exe fails to
              correctly merge .ctors input sections (containing C++
              global constructor pointers) from object files compiled by
              a modern GCC (16.1.0, MinGW-w64/MSYS2) into the final
              __CTOR_LIST__ array — even though the linker script
              (identical KEEP(*(.ctors)) rule, confirmed via ld.exe
              --verbose on both linkers) is present in both the old
              bundled ld.exe and a current MSYS2 ld.exe.<br>
              <br>
              Evidence:<br>
              <br>
                  A raw hex dump of __CTOR_LIST__ in an FPC-linked
              executable (with 10 real global constructors from a
              statically-linked FLTK/CFLTK library present and confirmed
              via nm) shows: sentinel (-1) immediately followed by
              terminator (0) — zero constructor pointers, despite the
              constructor functions (_GLOBAL__sub_I_*) physically
              existing in the binary.<br>
              <br>
                  The same source compiled and linked natively with
              g++.exe/current MSYS2 ld.exe produces a fully populated
              __CTOR_LIST__ with all 10 pointers correctly resolved to
              the matching _GLOBAL__sub_I_* addresses.<br>
              <br>
                  Attempting to relink the FPC-built binary with the
              current MSYS2 ld.exe (via -FD<path>) fails with
              illegal relocation type 0 / invalid section index errors
              on FPC's own RTL object files (sysutils.o, math.o) —
              indicating FPC's internal object emitter and modern
              binutils have diverged in mutually incompatible ways.
              rtl\sysutils.o: illegal relocation type 0 at address 0 etc<br>
              <br>
                  The input .o files from the affected FLTK library use
              COMDAT sections (LINK_ONCE_DISCARD) extensively (confirmed
              via objdump -h), which may be related to how the old
              ld.exe mishandles their .ctors content during merging —
              this is hypothesis<br>
              <br>
                  Consequently, statically linking modern C++ libraries
              (FLTK/CFLTK, built with current MinGW-w64/GCC) into an
              FPC/Lazarus Windows executable silently drops all global
              C++ constructors, causing use of uninitialized static
              objects downstream (observed as intermittent access
              violations depending on which code paths touch affected
              statics).<br>
              <br>
              Workaround currently used: manually enumerating
              _GLOBAL__sub_I_* symbols via nm on the linked (even if
              crashing) executable, globalizing their linkage scope via
              objcopy --globalize-symbol (they are emitted as local/t
              symbols), and generating a small Pascal unit that calls
              them all explicitly at program startup. This resolves some
              but not all downstream issues, suggesting missing
              constructor invocation is necessary but possibly not
              sufficient — full mainCRTStartup context
              (TLS/locale/guard-variable state) may also matter for some
              lazily-initialized C++ singletons. - this is last
              hypothesis<br>
              <br>
              Question for the list: Is there a newer/beta ld.exe (or
              plan to update the bundled binutils) for the Windows FPC
              toolchain that correctly handles .ctors/COMDAT sections as
              emitted by current GCC, without breaking compatibility
              with FPC's own object file emitter?</span></span></span></p>
      <p><br>
      </p>
      <p><span class="HwtZe" lang="en"><span class="jCAhz ChMk0b"><span
              class="ryNqvb"><br>
            </span></span></span></p>
      <br>
      <fieldset class="moz-mime-attachment-header"></fieldset>
      <pre wrap="" class="moz-quote-pre">_______________________________________________
fpc-pascal maillist  -  <a class="moz-txt-link-abbreviated" href="mailto:fpc-pascal@lists.freepascal.org">fpc-pascal@lists.freepascal.org</a>
<a class="moz-txt-link-freetext" href="https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal">https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal</a>
</pre>
    </blockquote>
  </body>
</html>