6.3 and 6.2.1 Compatibility Notes
Date of this edition: August 17, 2007
This note describes compatibility issues between QNX Momentics 6.3 and 6.2.1:
- Environment variables
- C code
- C++ code
- Board Support Packages (BSPs)
- RPC library
- 64-bit "large file" libc/filesystem support
You can find the latest version of this document on our website: http://www.qnx.com/.
To switch between building QNX Neutrino 6.2.1 and QNX Neutrino 6.3 applications using the Momentics IDE:
- Choose to open the Preferences dialog box.
- Select QNX in the preferences tree.
- Select QNX Momentics 6.3.2 or QNX Momentics 6.2.1 in the Select Install field to build for the specified target.
- Click Apply, then OK.
The IDE operates independently of the environment variables used to locate files on the development host.
QNX Momentics 6.3 uses these environment variables to locate files on the host machine:
- The location of included *.mk files.
- The location of host-specific files.
- The location of target-related components on the host machine.
- The location of the configuration files and licenses for QNX Momentics.
The qconfig utility automatically sets these variables according to the version of QNX Momentics that you specified. It also modifies the search path so that you use the binaries from the version you selected. For more information, see:
- the IDE Concepts chapter of the IDE User's Guide
- the Compiling and Debugging chapter of the Neutrino Programmer's Guide
- the entry for qconfig in the Utilities Reference.
Under Windows, you can launch the Configuration utility from the Start menu to select which version of QNX Momentics to use. This utility automatically sets these variables based on the version you select. For more information, see QWinCfg in the Utilities Reference.
In general, C applications compiled with 6.2.1 will run under 6.3. They shouldn't be affected by anything other than the tools-related issues. You might have to update drivers and resource managers. For more information, see:
We have moved to new versions of the Dinkum library and compiler:
|C++ library||OS version|
|libcpp.so.3||6.3 (compiled with GCC 2.95.3)|
|libcpp.so.4||6.3 (compiled with GCC 3.3.5)|
Note also that the default C++ libraries have moved from the common library directory $QNX_TARGET/CPU/lib to the GCC version subdirectory. For example, the x86 libcpp.so for GCC 3.3.5 is now:
$QNX_TARGET/x86/lib/gcc/3.3.5/libcpp.so --> ../../libcpp.so.4
A C++ application compiled with 6.3 must run with the 6.3 version of the C++ library.
Any 6.2.1 binaries will still run, but will require the 6.2.1 version of the C++ library (libcpp.so.2) to reside on the target system.
|GCC 2.95.3 (from 6.2.1 or 6.3) and GCC 3.3.5 use different C++ ABIs and have different name mangling. As a result, you can't link C++ binaries (objects, executables, libraries) built with GCC 2.95.3 with binaries built with GCC 3.3.5.|
QNX Momentics 6.3 has some new directories for C++ header files:
- $QNX_TARGET/usr/include/cpp/c (Dinkum)
- $QNX_TARGET/usr/include/cpp/embedded (Dinkum)
- $QNX_TARGET/usr/include/c++/3.3.5 (GNU -- not recommended)
If you use qcc, you shouldn't have to change anything because the configuration files include these directories. If you create your own Makefiles, and you aren't using qcc, then you should modify them to look in these directories for header files.
- Between the 2.10.1 version of the
GNU linker in 6.2.1 and the 2.12.1 version in
6.3.0, a bug was fixed in the handling of
relocation addends for SH targets. As a result of this fix,
SH startup binaries (e.g. startup-systemh) that
were created prior to 6.3.0 won't work correctly
if included in a boot image generated in 6.3.
Workaround: Rebuild the startup binary using 6.3. The resulting startup will work with both 6.2.1 and 6.3.
- ARM, SH4, and X86 binaries built with GCC under 6.2.x
have a potential incompatibility with binaries compiled
The 6.2 GCC incorrectly changed the alignments of long longs from 4 to 8 bytes on those platforms whenever Neutrino system headers were used. This violates the ABI for those architectures; it has been fixed in 6.3.0.
For ARM, SH4, and, X86 architectures:
- When both old and new binaries use only the standard inttypes.h 8-byte types (uint64_t and int64_t) they will be compatible.
- If old binaries or objects use 8-byte C primitive types (e.g. long long) in structures without explicitly setting alignments and if the structure values are communicated in some way between the two binaries or objects, they will not be compatible.
- The qcc compiler no longer links applications against the math library, libm, by default.
Drivers created with the 6.2.1 version of the following DDKs should be compatible with 6.3:
- Character -- any power-managed serial drivers that you wrote with 6.2.1 will need minor changes to get them to compile under 6.3. The devc-sersci serial driver has been updated for 6.3.0.
We don't guarantee that drivers created with the 6.2.1 version of the following DDKs are compatible with 6.3:
-- network drivers developed based on the earlier Network DDK should
still work under 6.3 if you're using the original version of Qnet
but not if you're using the new lightweight Qnet (the default in 6.3).
To determine which version you're using, type:
ls -l /lib/dll/npm-qnet.so
To use the original Qnet, make npm-qnet.so a symbolic link to npm-qnet-compat.so instead of to npm-qnet-l4_lite.so.
If you're using the new lightweight Qnet, a network driver developed with 6.2 could malfunction because the assignment of the bits in the flags field of the npkt_t structure has changed. See _NPKT_ORG_MASK and _NPKT_SCRATCH_MASK in <sys/io-net.h>.
The driver can use the eight most significant bits while it's processing a packet. The driver shouldn't make assumptions about the state of these bits when it receives a packet from the upper layers.
The next four most significant bits are for the use of the originator of a packet. The driver can use these flags for packets being sent upstream. If a packet didn't originate with the driver, the driver must not alter these flags.
We recommended you update the drivers to use the latest Network DDK structure. For more information, see the Network DDK documentation.
- 6.2.1 IPLs are compatible with 6.3.
- Other than PPC 600/700/74xx/82xx (see the release notes), all 6.2.1 startups are source-compatible with 6.3. Recompile your startup code against the 6.3 startup library.
- Most 6.2.1 applications will continue to work unmodified on 6.3. They will automatically use the provided legacy libraries. If you want to remove dependency on the legacy libraries, you must recompile your applications.
- The Pt_LIST_INACTIVE bit for
Pt_ARG_LIST_FLAGS (defined by PtGenList
has been deleted;
its value is now used by Pt_LIST_HSCROLLBAR_AS_REQUIRED.
If your applications set Pt_LIST_INACTIVE, change them to set Pt_BLOCKED in the widget's Pt_ARG_FLAGS. If you don't, an inactive list will become active and might get a horizontal scrollbar.
The Photon Application Builder automatically converts the flags for you.
- The format of the configuration file for the screen saver has changed, but the new savercfg and saver utilities can read both old and new formats. The new savercfg writes only the new format, so the old format will be lost once you change your settings. The transition is essentially transparent from the user's point of view, but anyone sharing their home directory between 6.3/6.2.x platforms should be aware of this.
In 6.3, dinit now creates long filenames by default. You can disable support for long filenames by specifying the -N option. (Ref# 17642)
|This is the reverse of the behavior of 6.2.1; the -N option formerly enabled support for long filenames.|
For more information about long filenames, see the description of the QNX 4 filesystem in the Working with Filesystems chapter of the Neutrino User's Guide.
Timeouts for clnt_broadcast() have changed. In 6.2 and earlier, timeout and retransmission occurs at 4 seconds and increases by 2 seconds for every timeout after that to a max of 14-second timeouts, resulting in 6 retransmissions.
In 6.3, timeout and retransmission occurs at 4 seconds and doubles after that to a max of 8 seconds, resulting in 2 retransmissions. You can alter timeout values by calling the lower-level call rpc_broadcast_exp().
The value of FD_SETSIZE has changed from 32 to 256. This affects the size of the fd_set objects that you pass to select().
This means that by default the highest allowable fd number for FD_SET(fd, &set) is 255.
Any use of fd_set within data structures will therefore cause a change in structure size, so you should do a global recompile.
|The global recompile should include all application code, as well as library code that would be referencing fd_set or structures containing fd_set. If you don't recompile, you may see random corruption and crashes.|
To make the value higher, #define FD_SETSIZE before including <sys/select.h>. But make sure this is done consistently throughout your modules.
If you don't want to cause a global compile, you can #define FD_SETSIZE 32 before including <sys/select.h> (or -DFD_SETSIZE=32 on the command line) to set it back to the old size, but make sure this setting is consistently applied to all your code.
QNX Neutrino 6.3 implements the X/Open Largefile Support extensions (see http://en.wikipedia.org/wiki/Large_file_support).
A large file is a regular file whose size is greater than or equal to the previous limit of 2 GB (the maximum size representable in a 32-bit signed integer).
For a discussion on the impact these changes have on application code, and how programmers can access this functionality, see http://wwws.sun.com/software/whitepapers/wp-largefiles/largefiles.pdf. This section gives a brief summary of those documents and attempts to highlight potential issues for application code.
|QNX Neutrino 6.3 doesn't introduce an underlying 64-bit filesystem (the fs-cd, fs-dos, fs-ext2, and fs-qnx4 formats retain 32-bit on-disk fields). It contains extensions to libc that allow for the future existence and use of a 64-bit filesystem.|
A client application can be one of the following:
- Safe for large files
- Such an application doesn't cause data loss or corruption when it
encounters a large file. This is the default model, and requires
no code or compilation changes (provided the code already checks
for and handles errors returned from all system routines involving
The libc and filesystem managers (themselves using libc/iofunc) now perform additional checks that prevent such a client from obtaining access to a large file, by failing open(), stat(), readdir(), etc. operations with an EOVERFLOW error.
If necessary, this mode can be explicitly forced by defining _FILE_OFFSET_BITS=32 before including any system headers (for example via CCFLAGS in common.mk). Leaving this symbol undefined is the same as defining it to have the value 32.
This definition causes all filesystem interfaces (such as open()), structures (such as struct dirent and struct stat), and relevant types (such as off_t and ino_t) to be 32-bit. Note that the structures themselves are always sized for 64-bits (for message-passing consistency), but in this mode consist of 32-bit fields and 32-bit *_hi fields for padding where appropriate. Calls to filesystem interfaces such as open(), stat(), etc. link directly to the corresponding open(), stat(), etc. libc routine.
- Aware of large files
- Such an application can process large files. This may require
code and compilation changes to ensure the proper data types
are used. For example, use the appropriate POSIX data type
off_t, instead of int or long,
to represent file sizes
and offsets. Changes may also be required in output formatting
strings, converting %d or %ld to %lld
when displaying such values, and in input parsing, using
strtoll() or atoll().
This mode is explicitly forced by defining _FILE_OFFSET_BITS=64 before including any system headers (for example via CCFLAGS in common.mk).
This definition causes all filesystem interfaces (such as open()), structures (such as struct dirent and struct stat), and relevant types (such as off_t and ino_t) to be 64-bit. Note that the structures themselves are always sized for 64-bits (for message-passing consistency), and in this mode the full 64-bit value is accessible. Calls to filesystem interfaces such as open(), stat(), etc. are mapped (transparently, at link time) in the executable to the corresponding open64(), stat64(), etc. libc routine.
- Explicit or mixed mode
- Such an application accesses large files, where necessary, using
explicit 64-bit types and filesystem interfaces, while the
default interface remains 32-bit. Both interfaces are available
to the program, which thus has the choice of when to manipulate
This mode is selected by defining _LARGEFILE64_SOURCE=1 before including any system headers (for example via CCFLAGS in common.mk). It doesn't make any sense to also define _FILE_OFFSET_BITS=64 in this case.
This definition causes the explicit 64-bit variants of all filesystem interfaces, structures, and relevant types to be exported into the namespace. For example, open64(), struct stat64, and off64_t. Such an application must also address the programming considerations above and be both safe with, and aware of, large files.
A server (resource manager) may support 32-bit or 64-bit objects. The selection, in addition to any programming considerations discussed above and in the referenced documents, is made at compile-time by the _FILE_OFFSET_BITS and _IOFUNC_OFFSET_BITS defines, before including any system headers.
The libc and iofunc library has been extended to perform additional checks as required by the X/Open Largefile Support specification. In particular, if the client isn't aware of large files, new tests within the library generate appropriate errors. A server using the standard iofunc_open(), iofunc_read_verify(), iofunc_write_verify(), iofunc_space_verify(), and iofunc_lock() routines thus automatically enforce appropriate client access semantics.
Server code should always use iofunc_attr_init() to initialize their internal object state, as this ensures that all fields are fully zeroed. _IO_STAT handling should use iofunc_stat(), to ensure the struct stat response is fully populated. For other functionality not having a default iofunc implementation, such as _IO_READ for directories and certain filesystem-related _IO_DEVCTL codes, the server code itself is responsible for ensuring the data structures are correctly manipulated.
Take care, in servers not compiled with _FILE_OFFSET_BITS=64, to fully populate reply message data structures. For example, a 32-bit struct dirent (used in _IO_READ handling of directories) contains two fields, d_ino_hi and d_offset_hi, which aren't modified by assignment to the 32-bit d_ino and d_offset fields. The resulting uninitialized 64-bit value then fails the range checks that the libc readdir() routine performs for a client that's safe for large files, causing the file entry to be skipped.
There are several solutions to this situation:
- Build the server to be aware of large files (_FILE_OFFSET_BITS=64). This makes the relevant fields of all structures explicitly 64-bit, and a simple assignment completely initializes them.
- Zero-fill the entire structure prior to field assignment.
memset(dp, 0, sizeof(struct dirent));
- Conditionally zero the relevant extended fields only if not
being compiled to be aware of large files.
#if !defined(_FILE_OFFSET_BITS) || _FILE_OFFSET_BITS == 32 dp->d_ino_hi = 0, dp->d_offset_hi = 0; #endif
A similar situation exists for the struct statvfs response to a DCMD_FSYS_STATVFS devctl(), which contains many 64-bit fields (f_blocks, f_bfree, f_bavail, f_files, f_ffree, and f_favail) or their *_hi components.
One potentially good compilation environment for a 32-bit server is to specify _FILE_OFFSET_BITS=64 and _IOFUNC_OFFSET_BITS=32. This definition causes:
- the internal data structures (such as iofunc_ocb_t and iofunc_attr_t) to have 32-bit fields, allowing smaller, more efficient code generation, lossless intermediate use of integral types, and use of traditional %d format conversions
- external/interface data structures (such as struct dirent and struct stat) to be defined with 64-bit fields. The standard C widening rules during their assignment fully populate the affected external fields from the internal representations. Make sure there are no unwanted sign-extension artifacts (for example, if you use a full 32-bit memory address as a unique inode number, you need to do some type casting).
Copyright © 2004-2007, QNX Software Systems GmbH & Co. KG. All rights reserved.