Possibly incorrect definiton of IMAGE_TLS_DIRECTORY64 lazarus / 64-FPC development ---------------------------------------------------------------------- 440bx · 2018-10-06 01:03 Hello, When using the "windows" unit definition of IMAGE_TLS_DIRECTORY64, the value obtained for the Characteristics field is incorrect. The reason why isn't quite clear as the definition in struct.inc seems correct but, the offset used to access the Characteristic field is definitely incorrect (the offset used in the assembly code is off by 4.) Below is a short example that reproduces the problem.Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i {$MODE OBJFPC                        } {$MODESWITCH     ADVANCEDRECORDS     }{$MODESWITCH     TYPEHELPERS         }{$MODESWITCH     ALLOWINLINE       }{$MODESWITCH     RESULT              }{$MODESWITCH     PROPERTIES          } {$MODESWITCH     ANSISTRINGS-        }{$MODESWITCH     AUTODEREF-          }{$MODESWITCH     UNICODESTRINGS-     }{$MODESWITCH     POINTERTOPROCVAR-   } {$LONGSTRINGS    OFF                 }{$WRITEABLECONST ON                }{$TYPEDADDRESS   ON                  }  //{$define useinternaldefinition} // -------------------------------------------- ---------------------------------// NOTE: compile the program as a 64bit windows executable.// ------------------------------------------ ----------------------------------- program TlsDirectoryRecordLayout;  uses  windows,  sysutils  ; {$ifdef useinternaldefinition} // other than formatting, this definition seems equivalent to the one found in// struct.inc.  However, when using this definition the result is correct.// when using the defintion from the windows unit, the result is incorrect. type  _IMAGE_TLS_DIRECTORY64 = record     StartAddressOfRawData   : ULONGLONG;     EndAddressOfRawData     : ULONGLONG;     AddressOfIndex          : ULONGLONG;           { PDWORD }     AddressOfCallBacks      : ULONGLONG;           { PIMAGE_TLS_CALLBACK *; }     SizeOfZeroFill        : DWORD;      case longint of       0 : (             Characteristics : DWORD           );       1 : (             CharacteristicsFields : bitpacked record                Reserved0 : 0..$FFFFF;  // 5 nibbles=20 bits                Alignment : 0..$F;    // 4 bits                Reserved1 : 0..$FF;     // 8 bits           end           );  end;   TIMAGE_TLS_DIRECTORY64 =  _IMAGE_TLS_DIRECTORY64;  PIMAGE_TLS_DIRECTORY64 = ^TIMAGE_TLS_DIRECTORY64;     _IMAGE_TLS_DIRECTORY32 = record     StartAddressOfRawData   : DWORD;     EndAddressOfRawData     : DWORD;     AddressOfIndex          : DWORD;               { PDWORD }   AddressOfCallBacks      : DWORD;               { PIMAGE_TLS_CALLBACK * }     SizeOfZeroFill          : DWORD;      case longint of       0 : (             Characteristics : DWORD           );       1 : (           CharacteristicsFields : bitpacked  record                Reserved0 : 0..$FFFFF;  // 5 nibbles=20 bits                Alignment : 0..$F;      // 4 bits                Reserved1 : 0..$FF;     // 8 bits             end           );     end;  TIMAGE_TLS_DIRECTORY32 =  _IMAGE_TLS_DIRECTORY32;  PIMAGE_TLS_DIRECTORY32 = ^TIMAGE_TLS_DIRECTORY32;{$endif} type  // layout of a TLS directory entry in a PE file   TLS_DATA = packed record    f1 : qword;    f2 : qword;    f3 : qword;    f4 : qword;     f5 : DWORD;    f6 : DWORD;  end; const  // TLS directory values as they would appear in a 64bit PE file   // clang.exe and MS link.exe, among others, are examples of executables that  // specify TLS alignment.   TlsData : TLS_DATA =  (    f1 : $100041000;  // qwords    f2 : $100041212;    f3 : $10003b70C;    f4 : $10002e778;     f5 : $0;          // DWORD - sizeof zero fill  f6 : $00300000;   // DWORD - 4 byte align  );  function LoadTls(Tls : PIMAGE_TLS_DIRECTORY64) : boolean;var  TlsArray : array[0..5] of qword; begin  TlsArray[0] := Tls^.StartAddressOfRawData;  TlsArray[1] := Tls^.EndAddressOfRawData;  TlsArray[2] := Tls^.AddressOfIndex;  TlsArray[3] := Tls^.AddressOfCallbacks;  TlsArray[4] := Tls^.SizeOfZeroFill;   // when using the structure definition present in stuct.inc, the offset to  // the characteristics field is incorrect, it points 4 bytes past the field.   TlsArray[5] := Tls^.Characteristics;   writeln(IntToHex(TlsArray[0], 10));  writeln(IntToHex(TlsArray[1], 10));  writeln(IntToHex(TlsArray[2], 10));  writeln(IntToHex(TlsArray[3], 10));  writeln(IntToHex(TlsArray[4], 10));   writeln;  writeln('The value below should NOT be zero (0) - s/b : 0000300000');  writeln;   writeln(IntToHex(TlsArray[5], 10));   result := true;end; begin  LoadTls(PIMAGE_TLS_DIRECTORY64(@TlsData));   writeln;  writeln('press any key to end this program');   readln;end.  Uncomment the define "useinternaldefinition" to observe the difference in the Characteristics. The first impression is that the definition of IMAGE_TLS_DIRECTORY64 in the Windows unit is incorrect but, it does look right. ---------------------------------------------------------------------- Thaddy · 2018-10-06 05:39 My first impression is that somewhere the packsettings play an issue: natural alignment will probably be a qword alignment causing an off by four for the variant case. (as opposed to 32 bit) Try {$packrecords c} or a reverse definition of the variant part (bitpacked part first) Also turn optimizations off to test if the compiler maybe did record field re-ordering (unlikely, but a possible optimization) ---------------------------------------------------------------------- ASerge · 2018-10-06 06:57 Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i {$APPTYPE CONSOLE} uses Windows; type // Copied from struct.inc  _IMAGE_TLS_DIRECTORY64 =  record      StartAddressOfRawData : ULONGLONG;      EndAddressOfRawData : ULONGLONG;      AddressOfIndex : ULONGLONG;               { PDWORD }      AddressOfCallBacks : ULONGLONG;           { PIMAGE_TLS_CALLBACK *; }      SizeOfZeroFill : DWORD;          case longint of            0 : ( Characteristics : DWORD );            1 : ( CharacteristicsFields:  bitpacked record                                Reserved0 : 0..$FFFFF; // 5 nibbles=20 bits                                  Alignment : 0..$F;      // 4 bits                                  Reserved1 : 0..$FF;     // 8 bits              end );    end; begin  Writeln(SizeOf(_IMAGE_TLS_DIRECTORY64));  Writeln(SizeOf(Windows._IMAGE_TLS_DIRECTORY64));  Readln;end. In fpc 3.0.4 40 and 48, in fpc 3.3.1 40 and 40. ---------------------------------------------------------------------- marcov · 2018-10-06 10:56 It should be 40, I did a printf with visual studio. IIRC some image structs had 8 byte packing and some not, and there was a bugreport about it, and it got reviewed. ---------------------------------------------------------------------- 440bx · 2018-10-06 13:18 Quote from: marcov on October 06, 2018, 12:56:34 pmIt should be 40, I did a printf with visual studio. IIRC some image structs had 8 byte packing and some not, and there was a bugreport about it, and it got reviewed. I got so focused on the problem this was causing that I forgot to mention it is with FPC 3.0.4 (release) under Win 7, 64 bit. ETA: reported it as a bug: 0034395 ---------------------------------------------------------------------- engkin · 2018-10-06 16:33 Quote from: ASerge on October 06, 2018, 08:57:28 am... In fpc 3.0.4 40 and 48, in fpc 3.3.1 40 and 40. ---------------------------------------------------------------------- 440bx · 2018-10-06 17:37 Are problems of this kind "back fixed" or updating to the latest version the only alternative ? ---------------------------------------------------------------------- Cyrax · 2018-10-06 17:43 Quote from: 440bx on October 06, 2018, 07:37:33 pmAre problems of this kind "back fixed" or updating to the latest version the only alternative ? Yes, updating to latest is the only way. There will be stable release of 3.2.0 in the future, where this should be fixed. ---------------------------------------------------------------------- 440bx · 2018-10-06 18:40 Quote from: Cyrax on October 06, 2018, 07:43:59 pmQuote from: 440bx on October 06, 2018, 07:37:33 pmAre problems of this kind "back fixed" or updating to the latest version the only alternative ? Yes, updating to latest is the only way. There will be stable release of 3.2.0 in the future, where this should be fixed. Thank you.  I'll wait for the stable release, in the meantime, I'll just work around it.