• R/O
  • SSH

SOM-Delphi-Wiki: Commit

Markdown wiki backup


Commit MetaInfo

Revision214240171b447013c6d19c34352b57e95a05a06d (tree)
Zeit2016-10-27 16:33:46
AutorOCTAGRAM <bo_ <gen@octa...>
CommiterOCTAGRAM <bo_

Log Message

DTS sample flags; more description; TypeCode_size test results

Ändern Zusammenfassung

Diff

diff -r a2fb577d02e3 -r 214240171b44 Known differences between SOM 2.1 and SOM 3.0.md
--- a/Known differences between SOM 2.1 and SOM 3.0.md Wed Oct 26 21:21:11 2016 +0000
+++ b/Known differences between SOM 2.1 and SOM 3.0.md Thu Oct 27 07:33:46 2016 +0000
@@ -4,40 +4,131 @@
44
55 VisualAge for C++ allocates as little space for enum as possible (controlled by /Su switch), while Microsoft C allocates int (4 bytes). This is notable when opening emitdef.dll (or any other emitter) in IDA. Where SOM 2.1 has "dword ptr [eax+4]", SOM 3.0 has "byte ptr [eax+4]". All Emitter Framework enums are affected! They are hacked to be C enums as opposed to normal SOM enums.
66
7+This is a quote from VisualAge for C++ User's Guide:
8+Use /Su to control the size of enum variables. If you do not provide a size, all enum variables are made 4 bytes.
9+By default, the compiler uses the SAA rules: make all enum variables the size of the smallest integral type that can contain all variables.
10+You can specify the following sizes:
11+ /Su[+] Make all enum variables 4 bytes.
12+ /Su1 Make all enum variables 1 byte.
13+ /Su2 Make all enum variables 2 bytes.
14+ /Su4 Make all enum variables 4 bytes.
15+
716 With regards to the switches used to build samples (found in samples\VACMAKE.HD and samples\MSCMAKE.HD):
817
9-SOM 3.0:
18+SOM 3.0:
1019 CFLAGSCOMMON = /Ti /O- /Os- /W1 /H128 /Q+ /c /Gd+ /Gm+
1120
12-SOM 2.1:
21+SOM 2.1:
1322 CFLAGSCOMMON = /Ti /O- /Os- /W1 /H128 /Gs+ /Sp1 /Q+ /c /Gd+ /Gm+
1423
24+/Ti Generate debugger information.
25+/O- Optimize code.
26+/Os- Invoke the instruction scheduler.
27+/W1 Set severity level of messages the compiler produces and counts.
28+/H128 Set maximum length of external names.
29+/Gs+ Remove stack probes.
30+/Sp1 Specify alignment or packing of data items within structures and unions.
31+/Q+ Suppress the compiler logo when invoking the compiler.
32+/Gd+ Dynamically link to the runtime library, instead of linking statically.
33+/Gm+ Link with the multithread library, instead of the single-thread library.
34+
1535 You should see the difference here.
1636
17-/Gs+ Remove stack probes
18-/Sp1 Packing of data items
37+/Gs+ Remove stack probes.
38+/Sp1 Specify alignment or packing of data items within structures and unions.
1939
20-SOM 2.1 (MSVC):
40+The default is /Sp8.
41+
42+This is VisualAge for C++ User Guide again:
43+Use /Sp to specify alignment or packing of data items within structures and unions.
44+By default, structures and unions are aligned along 8-byte boundaries (normal alignment).
45+/Sp is equivalent to /Sp1.
46+
47+SOM 2.1 (MSVC):
2148 CFLAGSCOMMON = /MT /G4 /Gs /Zp /Od /H128 /Zi /c /D_WIN32
2249
23-/MT
24-/G4 G4 386 instructions, optimize for 486
25-/Gs Controls stack probes.
26-/Zp Packs structure members.
27-/Od Disables optimization.
28-/H128 Deprecated. Restricts the length of external (public) names.
29-/Zi Generates complete debugging information.
30-/c
31-/D_WIN32
50+/MT
51+/G4 G4 386 instructions, optimize for 486
52+/Gs Controls stack probes.
53+/Zp Packs structure members.
54+/Od Disables optimization.
55+/H128 Deprecated. Restricts the length of external (public) names.
56+/Zi Generates complete debugging information.
57+/c
58+/D_WIN32
3259
3360 So it looks like SOM 2.1 packs structures, there are switches for both Microsoft C and VAC; and SOM 3.0 does not. At the moment no any known record can exhibit the difference, but this should be further investigated, and Delphi records should probably be made packed ones.
3461
35-Also note the difference in headers:
36-2.1:
37-typedef enum completion_status {YES, NO, MAYBE} completion_status;
38-3.0:
39-typedef enum completion_status {YES, NO, MAYBE,
40- completion_status_MAX = 2147483647 /* ensure mapped as 4 bytes */
41-} completion_status;
62+Also note the difference in headers:
63+2.1:
64+typedef enum completion_status {YES, NO, MAYBE} completion_status;
65+3.0:
66+typedef enum completion_status {YES, NO, MAYBE,
67+ completion_status_MAX = 2147483647 /* ensure mapped as 4 bytes */
68+} completion_status;
4269
43-As soon as MSVC compiler is used for SOM 2.1 samples, the enum is 4 bytes and consistent with SOM DLL ABI, but VAC compiler is supposedly broken. /Sp1 should make the structure Environment packed, change size and offsets in Environment. That makes it harder to verify assumptions about ABI. The first option is IDA, it unveils how do original DLLs work with data. The second option is to construct custom tk_struct TypeCodes and check tcSize on them.
\ No newline at end of file
70+As soon as MSVC compiler is used for SOM 2.1 samples, the enum is 4 bytes and consistent with SOM DLL ABI, but VAC compiler is supposedly broken. /Sp1 should make the structure Environment packed, change size and offsets in Environment. That makes it harder to verify assumptions about ABI. The first option is IDA, it unveils how do original DLLs work with data. The second option is to construct custom tk_struct TypeCodes and check tcSize on them.
71+
72+Also, IBM VisualAge C++ v3.5 has DirectToSOM sample, and it has independent flags:
73+
74+DEBUGFLAGS=/Ti /O- /Os-
75+BROWSEFLAGS=/Fb
76+PERFLAGS=/Gh
77+CPPFLAGS=$(DEBUGFLAGS) $(BROWSEFLAGS) $(PERFLAGS)
78+
79+Note that "/Sp1 Packing of data items" is not present, and so is "/Su" for enum sizes. IDA shows that SOM_CreateLocalEnvironment() macro in xhmain.cpp expands into SOMCalloc for 16 bytes. So enum size might be 1 here, but aligned pointers after "exception_type" expand this structure into 16-byte one. Unfortunatelly, xhmain.cpp does not check __SOMEnv->_major.
80+
81+And the final test is to use TypeCode_size on hand-made types:
82+
83+
84+```
85+#!delphi
86+
87+function TypeCodeNew(tag: TCKind): TypeCode; cdecl; varargs; external 'somtc.dll' name 'tcNew';
88+
89+procedure TestAlignmentAndSize;
90+var
91+ MyTC: TypeCode;
92+begin
93+ MyTC := TypeCodeNew(tk_struct, 'Test_1',
94+ 'Byte', TypeCodeNew(tk_octet),
95+ 'Integer', TypeCodeNew(tk_long),
96+ nil);
97+ WriteLn('Test_1 size: ', MyTC.Size);
98+ MyTC.Free;
99+ MyTC := TypeCodeNew(tk_struct, 'Test_2',
100+ 'Byte', TypeCodeNew(tk_octet),
101+ 'Subrecord', TypeCodeNew(tk_struct, 'Test_1',
102+ 'Byte', TypeCodeNew(tk_octet),
103+ 'Integer', TypeCodeNew(tk_long),
104+ nil),
105+ nil);
106+ WriteLn('Test_2 size: ', MyTC.Size);
107+ MyTC.Free;
108+ MyTC := TypeCodeNew(tk_struct, 'Test_3',
109+ 'Byte', TypeCodeNew(tk_octet),
110+ 'Subrecord', TypeCodeNew(tk_struct, 'Test_4',
111+ 'Byte', TypeCodeNew(tk_octet),
112+ 'Byte', TypeCodeNew(tk_octet),
113+ 'Integer', TypeCodeNew(tk_long),
114+ nil),
115+ nil);
116+ WriteLn('Test_3 size: ', MyTC.Size);
117+ MyTC.Free;
118+end;
119+
120+(*
121+Output on SOM 2.1:
122+Test_1 size: 5
123+Test_2 size: 6
124+Test_3 size: 7
125+
126+Output on SOM 3.0:
127+Test_1 size: 8
128+Test_2 size: 12
129+Test_3 size: 12
130+*)
131+
132+```
133+
134+So, clearly, that's not just IBM developers mishandled compiler flags. That's indeed different ABI. But the issue with mishandled compiler flags is also present.
Show on old repository browser