fejlsøgning - statisk sammenkobling bryder debug executable på windows (mingw)

Indlæg af Hanne Mølgaard Plasc

Problem



Vores C ++-projekt bruger blandede dynamiske (Qt) og statiske (ffmpeg, portaudio) biblioteker. I øjeblikket forsøger jeg at sende det til Windows, og den fejlfinding, der er produceret af Mingw (via QtCreator) nægter at starte (fejlen er sådan og sådan er ikke en gyldig eksekverbar). Udgivelsen kørebar med den samme forbindelse starter (men har nogle problemer, jeg gerne vil debug).


For at indsnævre den mulige årsag til problemet lavede jeg et dummy-projekt, der ikke gør noget, bare links til det samme sæt af biblioteker, og det har nøjagtigt det samme problem. Så længe jeg deaktiverer linking til begge statiske biblioteker, fejler eksekverbare værker, så snart jeg aktiverer en af ​​dem, er fejlsøgningen eksekverbar brudt.


Jeg har ikke prøvet at bygge dll-versioner af ffmpeg og portaudio endnu, men jeg vil gerne forstå, hvad der går galt med sagen som det er.

Bedste reference


Dette skyldes en ubehagelig fejl i ld linkeren i MinGW-pakken, som er inkluderet i nogle Qt-downloads.


Den ld linker, der er inkluderet i MinGW 4.4.0-pakken, har en fejl i standard linker scriptet for placering af .debug\_pubtypes sektionen, hvor symboler eller nogle fejlretningsoplysninger bliver gemt. Linker scriptet forårsager den sektion at blive placeret på en virtuel adresse, som loader ikke kan lide (eller noget lignende). Nogle gange - hvis du ikke har symboler i billedet, eller hvis symbolerne er små nok (eller måske er der en anden faktor) problemet ikke vises.


Du har et par muligheder:



  • brug indstillingen -T <scriptfile> til at angive et korrekt linker script til ld

  • Opgradering til en nyere version af ld (version 2.21, der leveres med MinGW 4.5.2 fungerer fint).



Her er standard linker scriptet fra ld 2.21, hvilket skal fungere, hvis du sender det videre til den version, du har (desværre siger jeg ikke, hvad versionsnummeret af LD med problemet er - hvis du kunne droppe en kommentar om det, så jeg kan opdatere mine noter, jeg værdsætter det).


/* Default linker script, for normal executables */
OUTPUT\_FORMAT(pei-i386)
SEARCH\_DIR("/c/temp/gcc/dest/i686-pc-mingw32/lib"); SEARCH\_DIR("/c/temp/gcc/dest/lib"); SEARCH\_DIR("/usr/local/lib"); SEARCH\_DIR("/lib"); SEARCH\_DIR("/usr/lib");
SECTIONS
{
  /* Make the virtual address and file offset synced if the alignment is
     lower than the target page size. */
  . = SIZEOF\_HEADERS;
  . = ALIGN(\_\_section\_alignment\_\_);
  .text  \_\_image\_base\_\_ + ( \_\_section\_alignment\_\_ < 0x1000 ? . : \_\_section\_alignment\_\_ ) :
  {
     *(.init)
    *(.text)
    *(SORT(.text$*))
     *(.text.*)
    *(.glue\_7t)
    *(.glue\_7)
     \_\_\_CTOR\_LIST\_\_ = .; \_\_CTOR\_LIST\_\_ = . ;
            LONG (-1);*(.ctors); *(.ctor); *(SORT(.ctors.*));  LONG (0);
     \_\_\_DTOR\_LIST\_\_ = .; \_\_DTOR\_LIST\_\_ = . ;
            LONG (-1); *(.dtors); *(.dtor); *(SORT(.dtors.*));  LONG (0);
     *(.fini)
    /* ??? Why is .gcc\_exc here?  */
     *(.gcc\_exc)
    PROVIDE (etext = .);
     *(.gcc\_except\_table)
  }
  /* The Cygwin32 library uses a section to avoid copying certain data
     on fork.  This used to be named ".data".  The linker used
     to include this between \_\_data\_start\_\_ and \_\_data\_end\_\_, but that
     breaks building the cygwin32 dll.  Instead, we name the section
     ".data\_cygwin\_nocopy" and explictly include it after \_\_data\_end\_\_. */
  .data BLOCK(\_\_section\_alignment\_\_) :
  {
    \_\_data\_start\_\_ = . ;
    *(.data)
    *(.data2)
    *(SORT(.data$*))
    *(.jcr)
    \_\_data\_end\_\_ = . ;
    *(.data\_cygwin\_nocopy)
  }
  .rdata BLOCK(\_\_section\_alignment\_\_) :
  {
    *(.rdata)
             *(SORT(.rdata$*))
    \_\_\_RUNTIME\_PSEUDO\_RELOC\_LIST\_\_ = .;
    \_\_RUNTIME\_PSEUDO\_RELOC\_LIST\_\_ = .;
    *(.rdata\_runtime\_pseudo\_reloc)
    \_\_\_RUNTIME\_PSEUDO\_RELOC\_LIST\_END\_\_ = .;
    \_\_RUNTIME\_PSEUDO\_RELOC\_LIST\_END\_\_ = .;
  }
  .eh\_frame BLOCK(\_\_section\_alignment\_\_) :
  {
    *(.eh\_frame)
  }
  .pdata BLOCK(\_\_section\_alignment\_\_) :
  {
    *(.pdata)
  }
  .bss BLOCK(\_\_section\_alignment\_\_) :
  {
    \_\_bss\_start\_\_ = . ;
    *(.bss)
    *(COMMON)
    \_\_bss\_end\_\_ = . ;
  }
  .edata BLOCK(\_\_section\_alignment\_\_) :
  {
    *(.edata)
  }
  /DISCARD/ :
  {
    *(.debug$S)
    *(.debug$T)
    *(.debug$F)
    *(.drectve)
     *(.note.GNU-stack)
     *(.gnu.lto\_*)
  }
  .idata BLOCK(\_\_section\_alignment\_\_) :
  {
    /* This cannot currently be handled with grouped sections.
    See pe.em:sort\_sections.  */
    SORT(*)(.idata$2)
    SORT(*)(.idata$3)
    /* These zeroes mark the end of the import list.  */
    LONG (0); LONG (0); LONG (0); LONG (0); LONG (0);
    SORT(*)(.idata$4)
    \_\_IAT\_start\_\_ = .;
    SORT(*)(.idata$5)
    \_\_IAT\_end\_\_ = .;
    SORT(*)(.idata$6)
    SORT(*)(.idata$7)
  }
  .CRT BLOCK(\_\_section\_alignment\_\_) :
  {
    \_\_\_crt\_xc\_start\_\_ = . ;
    *(SORT(.CRT$XC*))  /* C initialization */
    \_\_\_crt\_xc\_end\_\_ = . ;
    \_\_\_crt\_xi\_start\_\_ = . ;
    *(SORT(.CRT$XI*))  /* C++ initialization */
    \_\_\_crt\_xi\_end\_\_ = . ;
    \_\_\_crt\_xl\_start\_\_ = . ;
    *(SORT(.CRT$XL*))  /* TLS callbacks */
    /* \_\_\_crt\_xl\_end\_\_ is defined in the TLS Directory support code */
    \_\_\_crt\_xp\_start\_\_ = . ;
    *(SORT(.CRT$XP*))  /* Pre-termination */
    \_\_\_crt\_xp\_end\_\_ = . ;
    \_\_\_crt\_xt\_start\_\_ = . ;
    *(SORT(.CRT$XT*))  /* Termination */
    \_\_\_crt\_xt\_end\_\_ = . ;
  }
  .tls BLOCK(\_\_section\_alignment\_\_) :
  {
    \_\_\_tls\_start\_\_ = . ;
    *(.tls)
    *(.tls$)
    *(SORT(.tls$*))
    \_\_\_tls\_end\_\_ = . ;
  }
  .endjunk BLOCK(\_\_section\_alignment\_\_) :
  {
    /* end is deprecated, don't use it */
    PROVIDE (end = .);
    PROVIDE ( \_end = .);
     \_\_end\_\_ = .;
  }
  .rsrc BLOCK(\_\_section\_alignment\_\_) :
  {
    *(.rsrc)
    *(SORT(.rsrc$*))
  }
  .reloc BLOCK(\_\_section\_alignment\_\_) :
  {
    *(.reloc)
  }
  .stab BLOCK(\_\_section\_alignment\_\_) (NOLOAD) :
  {
    *(.stab)
  }
  .stabstr BLOCK(\_\_section\_alignment\_\_) (NOLOAD) :
  {
    *(.stabstr)
  }
  /* DWARF debug sections.
     Symbols in the DWARF debugging sections are relative to the beginning
     of the section.  Unlike other targets that fake this by putting the
     section VMA at 0, the PE format will not allow it.  */
  /* DWARF 1.1 and DWARF 2.  */
  .debug\_aranges BLOCK(\_\_section\_alignment\_\_) (NOLOAD) :
  {
    *(.debug\_aranges)
  }
  .debug\_pubnames BLOCK(\_\_section\_alignment\_\_) (NOLOAD) :
  {
    *(.debug\_pubnames)
  }
  .debug\_pubtypes BLOCK(\_\_section\_alignment\_\_) (NOLOAD) :
  {
    *(.debug\_pubtypes)
  }
  /* DWARF 2.  */
  .debug\_info BLOCK(\_\_section\_alignment\_\_) (NOLOAD) :
  {
    *(.debug\_info) *(.gnu.linkonce.wi.*)
  }
  .debug\_abbrev BLOCK(\_\_section\_alignment\_\_) (NOLOAD) :
  {
    *(.debug\_abbrev)
  }
  .debug\_line BLOCK(\_\_section\_alignment\_\_) (NOLOAD) :
  {
    *(.debug\_line)
  }
  .debug\_frame BLOCK(\_\_section\_alignment\_\_) (NOLOAD) :
  {
    *(.debug\_frame)
  }
  .debug\_str BLOCK(\_\_section\_alignment\_\_) (NOLOAD) :
  {
    *(.debug\_str)
  }
  .debug\_loc BLOCK(\_\_section\_alignment\_\_) (NOLOAD) :
  {
    *(.debug\_loc)
  }
  .debug\_macinfo BLOCK(\_\_section\_alignment\_\_) (NOLOAD) :
  {
    *(.debug\_macinfo)
  }
  /* SGI/MIPS DWARF 2 extensions.  */
  .debug\_weaknames BLOCK(\_\_section\_alignment\_\_) (NOLOAD) :
  {
    *(.debug\_weaknames)
  }
  .debug\_funcnames BLOCK(\_\_section\_alignment\_\_) (NOLOAD) :
  {
    *(.debug\_funcnames)
  }
  .debug\_typenames BLOCK(\_\_section\_alignment\_\_) (NOLOAD) :
  {
    *(.debug\_typenames)
  }
  .debug\_varnames BLOCK(\_\_section\_alignment\_\_) (NOLOAD) :
  {
    *(.debug\_varnames)
  }
  /* DWARF 3.  */
  .debug\_ranges BLOCK(\_\_section\_alignment\_\_) (NOLOAD) :
  {
    *(.debug\_ranges)
  }
  /* DWARF 4.  */
  .debug\_types BLOCK(\_\_section\_alignment\_\_) (NOLOAD) :
  {
    *(.debug\_types) *(.gnu.linkonce.wt.*)
  }
}


Jeg har ikke noget imod at fortælle dig, at jeg var nødt til at gå igennem en uge med smerte for at finde ud af det. Windows giver slet ingen reel hjælp om årsagen til, at den eksekverbare er ugyldig og debugging - selv med cdb eller WinDBG fra 'Debugging Tools for Windows' - er lidt hjælp. Windows synes at fastslå, at PE'en er ugyldig fra dybt inde i loader i NT-kernen, og giver ikke nogen oplysninger, som jeg kunne finde om årsagen (det ville have været rart at have noget sat i hændelseslog eller noget).


Jeg har i sidste ende fundet ud af dette problem ved at bruge vinens (!!) sporing facilitet. Jeg spekulerer på, om den 'tjekkede' version af Windows ville give mere information om problemet, men jeg havde et helvede tid at få den downloadet og installeret.