Markdown wiki backup
Revision | 214240171b447013c6d19c34352b57e95a05a06d (tree) |
---|---|
Zeit | 2016-10-27 16:33:46 |
Autor | OCTAGRAM <bo_ <gen@octa...> |
Commiter | OCTAGRAM <bo_ |
DTS sample flags; more description; TypeCode_size test results
@@ -4,40 +4,131 @@ | ||
4 | 4 | |
5 | 5 | 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. |
6 | 6 | |
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 | + | |
7 | 16 | With regards to the switches used to build samples (found in samples\VACMAKE.HD and samples\MSCMAKE.HD): |
8 | 17 | |
9 | -SOM 3.0: | |
18 | +SOM 3.0: | |
10 | 19 | CFLAGSCOMMON = /Ti /O- /Os- /W1 /H128 /Q+ /c /Gd+ /Gm+ |
11 | 20 | |
12 | -SOM 2.1: | |
21 | +SOM 2.1: | |
13 | 22 | CFLAGSCOMMON = /Ti /O- /Os- /W1 /H128 /Gs+ /Sp1 /Q+ /c /Gd+ /Gm+ |
14 | 23 | |
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 | + | |
15 | 35 | You should see the difference here. |
16 | 36 | |
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. | |
19 | 39 | |
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): | |
21 | 48 | CFLAGSCOMMON = /MT /G4 /Gs /Zp /Od /H128 /Zi /c /D_WIN32 |
22 | 49 | |
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 | |
32 | 59 | |
33 | 60 | 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. |
34 | 61 | |
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; | |
42 | 69 | |
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. |