Offsets do not match
Problem: The offsets between fields in the GCC structures versus the IBM® compiler structures versus the assembler structures do not match.
elfaggr, an offline Linux® program provided with the z/TPF system, and assembler
listings to compare offsets between C/C++ structures and assembler
data macros (DSECTs). The source for elfaggr is in
the base/util/src directory and the executable is
in the linux/bin directory. To display the C/C++
structures that are included in a program, enter one of the following
commands on your Linux system:- elfaggr objectfilepath.o, where objectfilepath is the full path of the object file name.
- elfaggr csofilepath.so, where csofilepath is
the full path of the C shared object (CSO) file name. The following example shows an excerpt of the output displayed of the C/C++ structures that are included in the cvbv program. All structures in the header file or source file are part of the complete output. The cvbv program was specified by entering elfaggr cvbv.o or elfaggr base/load/CVBV.so on a Linux system.
0x 0 struct opcode_table_entry 0x 0 short unsigned int opcode 0x 4 int oplen 0x 8 unsigned char[38] description 0x 2E unsigned char[6] text 0x 34 DISASM_TYPE type 0x 38 int format_nbr 0x 40 struct opcode_table_entry* subtable
- Ensure that all fields defined are the same size. See Mapping data types for a list of C data types that have changed size between the IBM C/C++ compiler and GCC.
- 8-byte pointers and longs are forced to 8-byte boundaries in GCC. This can cause GCC to pad the structure to force boundary alignment where this padding did not exist in the IBM compiler or assembler structure.
- When bit fields are in unpacked structures, the padding that is
applied by various compilers can be different. For example, if you
defined a bit field in the following unpacked structure, GCC adds
2 bytes of padding between the c2 and myfield variables, but the IBM compiler does not.
struct mystruct { char c1; char c2; int myfield :24; char c3; }To address this difference, always pack the structure that contains the bit field. See Migrating your application programs for information about how to pack a structure.
Note: Consider bit-field variablemyfieldin the following example:
The following is an example of a correspondingstruct mystruct { ... int myfield :24; ...elfaggrdisplay:
Where:0x 0 struct mystruct ... 0x 11: 8 unsigned int myfield:18 ...- The offset for bit-field variable
myfieldis0x 11: 8, which means offset0x11+0x8bits (0x11bytes +0x1byte). This is equal to offset0x12(decimal 18). - The length of bit-field variable
myfieldis:18, which means that the field is0x18(decimal 24) bits long.
- The offset for bit-field variable
- If there is a pointer to a pointer to a 4-byte field, ensure that you use both
the
__ptr32_tdata type and the PTR32ATT attribute. For example, consider the following 4-byte field in thectk2structure in the c_ck2sn.h header file:
To keep the size of this field 4 bytes long, code the following:POINTER *ck2rvt1a; //void **ck2rvt1a#include <sys/types.h> __ptr32_t * PTR32ATT ck2rvt1a;If the PTR32ATT attribute is not specified, the size of this field will be 8 bytes and will not match the assembler structure.
- In the IBM compiler, enumerated data types use the smallest amount of storage possible based on the value of the enumerations. This means that the IBM compiler uses 1, 2, or 4 bytes for an enumerated type. The GCC always uses 4 bytes. As a result, the size of structures that contain enumerated types will change and the relative location of the enumerations will shift. See Mapping data types for more information about how to handle enumerated data types.
__attribute__((packed)) keyword and
attribution specification of the GCC compiler affects only the definition
of the data object that the statement directly applies to. If there
is a nested inner aggregate (structure or union) in this same definition,
the inner definition will not be packed unless __attribute__((packed)) is
applied to it as well. That is, packing an outer aggregate definition
will not pack any inner definition that might be present. This also is true for the _Packed qualifier of the z/OS® compiler; that is, if you specify the _Packed qualifier on a structure or union that contains a structure or union as a member, the qualifier is not passed on to the contained structure or union. You must specify the _Packed qualifier on any nested inner aggregate (structure or union) that is in this same definition.