The Case of GCC-5.1 and the Two C++ ABIs
allanmcrae.com
allanmcrae.com
[edit: clarified it isn't about the type of linking, it's about separate distribution of libs from apps that use the libs).
The value of dynamically linking common system libraries isn't performance (well, anymore), it's that your friendly distro maintainers can do a far, far better job than you at maintaining that software for you as bugs are fixed over time.
Now, Go isn't subject to the kind of severity of bug that C is, and their package management may be slick enough to make straightforward recompilation into the default deployment mode. But if that's true it's true in spite of the drawbacks of static linkage, not because of it.
If you assume that:
- people stop using a full OS to deploy their apps (in a containerized world, for example), so there's only a tiny attack surface,
- that only the application's dependencies exist (no reliance on distro-provided too) and are full specified (eg in a Gemfile.lock or equivalent),
- that a dev team is responsible for knowing about security vulns in their dependencies when they happen,
- that things like libjpeg are run in separate services which are completely locked down and dont have the ability to compromise another system,
Then this isn't an issue.
Lots of big ifs there, I'm aware.
Sure, there are performance implications. So you come up with complicated meta-streaming APIs to put as much of the intelligence into that "mediaserver" as possible. And on the other side you come up with complicated buffer sharing architectures and APIs to make sure that the output can go straight to the screen instead of back through the app. Oh, and there are (cough) "security" concerns too (which is the whole point to doing this all in a system process), so you need to drill those bits down not just through the userspace but into the driver and out through the HDCP pipeline nonsense below the kernel (which of course needs userspace helpers in most architectures, so up it all comes again through different drill holes...).
Er, rather, it is crazy, but for different reasons than you posit. You could totally make it run fast if you had to.
Again, I'm not saying it isn't crazy, just that it's possible, and that equivalent insanity is already afoot.
This is the part that falls down though. It sounds sane, but in the real world the "dev team" was a contractor hired for a one-off project six years ago, and the developers themselves were laid off last year when it folded.
Or the "dev team" is an open source website that hasn't been updated in three years, but hey -- they have this nice windows binary for you to pull and use and it still installs and works fine.
Just don't.
If only that were true. There are some packages which take hours to compile by themselves, even on beefy servers.
IIRC, you can go from zero to a complete desktop Gentoo system in 2-4 hours on an i7 desktop. But even this long is admittedly an annoyance most users would not want to endure on a regular basis for a modest increase in security. The main reason people use Gentoo seems to be configurability, not security.
Don't know about GP, but I can think of a few more: KDE, OpenOffice, Firefox (that alone takes about 2 hours on my quad-core Phenom), Chromium.
Consider a build where clang (c++11), gcc5 (c++11), and gcc4 (c++03) are used. gcc5 uses the new abi, gcc4 uses the old abi, clang uses the new abi headers but links to the old abi (since it doesn't yet support the new name mangling scheme).
I want to eliminate the idea that libraries are distributed separately from the application that uses them.
But no, of course I'm not suggesting that - and that's a good counter-example, thanks. Really, I believe that the idea that the OS distributes libraries like libjpeg as archaic (distros strike me as an awful idea, tbh). That's part of the application, and it's the application's responsibility to ship a fix.
You want to be able to update openssl for the heartbleed bug, and know "it's fixed on my system". Not "welp, just as soon as i finish getting new binaries from the 500 people who produce the software packages i use, I won't have a problem".
There is no really sane way to accomplish this goal without decoupling binaries and libraries (AFAIK, love to hear any other idea. Things like common intermediate forms for executables would work if you didn't allow inlining/etc) :)
Well, that's not going to happen in every case. In a world where AAA games are shipped almost completely broken (Batman passim), vendors are part of the problem.
We can go back to shipping software as complete units like we did in the cartridge/tape/floppy days. But doing so on anything connected to a network is extremely dangerous.
To take an example from your cloud enabled world (kids these days) that should be easily understandable from your perspective: How many people honestly update their version of rails and Ruby when a new one comes out? And how often does that happen on most projects in practice?
Do you think it's going to be any different if we stop having ABIs?
This is the type of dream that leads directly to a cold dark nightmare if you ever tried to implement it farther than an HN comment.
It's not about saving memory or disk space (although those are still very significant, especially on mobile). It's about allowing a program's components to evolve separately.
Dynamic linking is one way to ensure that all apps automatically get the correct clipboard implementation for the system they are running on. Of course this applies to all system features, not just copy/paste.
Of course C++ is really terrible at this. Its binary interface is very fragile: you can't add variables or virtual methods without breaking clients, and of course different STLs cannot interoperate. So for the case of C++ specifically, ABI compatibility is lipstick on a pig. Still, the gcc guys deserve props for their abundance of caution, and it does pay dividends for other tools (e.g. gdb) that have to understand the ABI.
True but if someone is dealing with syscalls on Windows they're programming something very unusual.
>so you really want to use kernel32.dll and friends or you're signing up for pain.
Why? There is no pain involved unless a function that isn't implemented in older versions is imported.
The file open/save dialogs embed Explorer and all its shell extensions, each of which is a DLL. These can vary from system to system.
Something similar is present on Linux with libnss; if you want to do username-userid lookups, you have to load the relevant libraries at runtime.
Go avoids this because the language designed in simpler ABI requirements, and also doesn't allow binary libraries at all (everything is expected to be source code). This completely avoids the problem since you only have one compiler producing all the components.
But this isn't always a good thing. There are some good reasons for prebuilt libraries. (I had the unfortunate need to recently compile a huge C++ library on a slow ARM based embedded machine without the help of a cross-compiler. It took about 14 hours to compile. And I had to do it twice because the first time the build flags were wrong.)
For more interesting perspective on dynamic vs. static libraries, read: iOS Static Libraries Are, Like, Really Bad, And Stuff (Radar 15800975)http://landonf.org/code/ios/Radar_15800975_iOS_Frameworks.20...
Yes, this is what I'm getting at! This mess of linking and ABIs is a mess, and it shouldn't exist unless it must, and it only must in very few cases.
Thanks for the link, I'll take a read.
edit: also, because I'm talking about PCs and not servers, I'm running very few apps, and most of them do not interact with the network. Strategies for securing servers do not necessarily make the right tradeoffs for personal machines.
The ability to update common components is a boon. Seriously. Not without concerns or flaws, as you correctly note. But overall, it's radically better than the alternative.
Second, you think that the cost of breakage and inconvenience is around equal to the cost of a serious malevolent attack. I disagree. I'd rather experience an issue a month where a program crashes and I have to install an update, if the alternative is someone getting access to my bank account, credit cards, or even personal, sensitive information that could harm me if taken out of context and made public.
Third, I think the reason you don't experience as many malevolent attacks is precisely because many, many PC users keep their systems updated, and the cost/reward for the attackers is low. If every single PC user had your attitude, and no one updated, the first CVE from Windows that was easy to exploit remotely (either via the network, or email + images, or whatever) would result in a skyrocket of successful attacks.
And finally, my own anecdotal evidence is in stark contrast to yours - I relatively rarely get any sort of library or system stability issues from keeping my systems up-to-date, but I have been attacked before, and it is a much larger inconvenience to get new credit cards, monitor my credit reports, and install counter-measures to prevent it from happening again.
You don't break such fundamental ABIs on a whim. If the libstdc++ ABI had changed, it would have broken every single bit of C++ code built with GCC4 over the last decade. Including code with transitive dependencies on the old ABI.
Rather than declaring this as a "silly feature", I think we might be better off thanking the developers concerned for solving a very hard problem and going the extra mile to ensure backward compatibility. They could have been lazy and said "ABI break! Flag day today: every user of GCC much rebuild the entire world and, by the way, none of your old software will run any longer", but they didn't. So clang hasn't got the new ABI quite right to match GCC, that's a minor niggle. It can be fixed. You can't fix breaking the whole world.
As an example, consider that the Mesa OpenGL C library internally uses libstdc++. If this was built using an incompatible new ABI, it would break every C++ program linked against the old ABI. And vice-versa. That game or expensive visualisation software you bought, that's not going to work any more. Stable ABIs matter.
[1] http://fedoramagazine.org/gcc-5-in-fedora-whats-an-abi-and-w...
In a few months time we'll all forget this was an issue since it will for all intents and purposes (for the end user and developer) be a completely transparent upgrade.
IIRC, one of the most significant was a change that made copy-on-write an invalid (or at least much more difficult) implementation for std::string, and gcc's std::string was CoW.
http://developerblog.redhat.com/2015/02/05/gcc5-and-the-c11-...
The issue here is solely that clang++ doesn't yet implement some of the requirements of the new ABI and so isn't fully compatible with it. This is a very different point.
libc++ is also versioned using namespaces, but no abi_tag