{$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.