Monday, March 29, 2004

libstdc++ and compatibility


I've been studying the C/C++ build and I think I learned some things:
  • glibc is inextricably linked with the Linux operating system. You can't run with a new glibc.
  • LD_LIBRARY_PATH can affect libc, but cannot affect ld-linux.so.2 (ld-2.3.2.so). It seems you can get around this with chroot, but then you have other problems.
  • glibc 2.3.2 has the symbol GLIBC_PRIVATE which is in ld-2.3.2.so, but not inld-2.2.x.
  • libstdc++ 3.2 (it comes with g++ 3.2) requires glibc 2.3. Redhat 7 ships with 2.2 or earlier. See previous point. You cannot take a libstdc++ from Redhat 9 and run it on Redhat 7 unless you upgrade glibc and just about everything else in the OS, at which point it's not really Redhat 7.
  • libstdc++ is more than STL. It's the C++ runtime and STL. Therefore STLport can never replace libstdc++.
  • I can chroot with Redhat 7 (actually Mandrake 8) and get my Redhat 9 compiled binary and libstdc++ 3.2 shared object. However, once I do that I can't do things like read /proc or modify /etc which is something we need to do.
  • Starting with g++ 3.2, libstdc++ is attempting to be forward/backwards compatible in its ABI where possible. At this point compatibility was completely broken.
  • Redhat 9 ships with compat-libstdc++ which contains the C++ runtime libraries for gcc 2.96 as used in Redhat 7.3. This means C++ stuff compiled on Redhat 7 will work on Redhat 9, but only when this package is installed.
  • glibc works very well forward/backwards compatibility-wise, with the GLIBC_2.0,GLIBC_2.1, etc. symbols. If you build a binary that is C only, it's probably going to run anywhere, as long as it's glibc v2 or better, preferably glibc v2.1.
  • It is impossible to statically link libstdc++ into an executable when exceptions are thrown/caught. This is because symbols such as _Unwind_DeleteExceptionexist in libgcc.so but do not exist in libgcc.a.

Sunday, March 14, 2004

perl and relocating its installation


While setting up our development system and source control, I'm taking the philosophy that all tools are to be checked into source control, not installed on individual machines; in that way a developer's tools are never out of date. Unfortunately some tools don't like this approach, they like to hard-code or "relocate" their position during installation.
One of those is perl.
This link explains a bit how ActivateState relocates perl on install.
What happens is that the @INC path must be embedded in the perl executable on
Unix platforms, or so they claim. When install.sh is run, it calls reloc_perl,
which uses an ActiveState perl module Relocate which then uses this trick to
replace things like
/tmp/.TheInstallScriptWasNotRunTheInstallScriptWasNotRunTheInstallScriptWasNotRun-perl/lib/5.8.0
with the appropriate path. Unfortunately, when I first tried this, the path just happens to be my home directory where I downloaded it.
By the way, there is only 0x80 (128) bytes of space to put the path in, so there is a limit to what location it can be relocated into.
So, the procedure I used to get an ActivePerl that works on anyone's machine no matter where their source directory is mapped to their file system:
  • Installed ActiveState Perl normally, into a place such as your home directory: in my case this was /home/jared.oberhaus/p4/tools/linux/ActivePerl-5.8.3.809
  • Found all instance of text and binary files under the installation directory that contain /home/jared.oberhaus and replaced them with the original files from the install tar. The original files still have encoded strings such as/tmp/.TheInstallScriptWasNotRunTheInstallScriptWasNotRunTheInstallScriptWasNotRun-perl/lib/5.8.0 inside them.
  • Submitted these files to source control as-is.
  • Modified ActiveState's install.sh by adding to it (not removing the original install procedures). First it links the magic /tmp path to the file location where the source control version is mapped. This is controlled by detecting where the install script exists and processing that. When reloc_perl executes it will copy everything into /home/user/p4/tools/linux/perl-5.8.3 and at the same time replace the magic /tmp string with the correct location.

Wednesday, March 3, 2004

Preventing System.exit()


You can prevent System.exit() by setting the appropriate thing in the SecurityManager. Try something like this in your JUnit test:
public void setUp() {
    System.setSecurityManager(new CatchSystemExit());
}
public void tearDown() {
    System.setSecurityManager(null);
}
private static class CatchSystemExit extends SecurityManager {
    /** @see SecurityManager */
    public void checkExit(int status) {
        m_exitCode = status;
        throw new SecurityException("System.exit() attempt caught");
    }
    /** @see SecurityManager */
    public void checkPermission(Permission perm, Object context) {
    }
    /** @see SecurityManager */
    public void checkPermission(Permission perm) {
    }
}