Solid Sands: the day that GNU-C++ -Os broke

We spent a good day of debugging a few of our C++ tests before a pattern emerged. We are working on a project to support freestanding C and C++ environments with the SuperTest test and validation suite for C and C++ compilers. A freestanding environment is defined to support only a subset of the C and C++ libraries. Its goal is to allow applications to run on targets that do not have an extensive run-time system like a proper OS. Instead, it allows programs to run on 'bare-metal'. This is useful for all kinds of embedded applications.

One of the goals in this project is to minimize the memory requirements of the SuperTest, so we use the compiler with the memory optimization option -Os.

Several C++ tests, related to exception handling and inheritance, suddenly failed in the new freestanding configuration.

When tests fail like this, the first thing to suspect is our own changes. After all, the compiler used is the default g++ compiler on a fully up-to-date x86 Ubuntu environment. Many thousands (millions?) of mission-critical systems use GNU-C++ and Ubuntu. Space-X, just to name a high-profile example, uses C++ and Linux on x86 in their rockets too.

Here is one such test. Yes, we know this is not nice C++, but we are not in the business of writing nice C++. Our job is to go near the edge of the language specification to verify the correct behavior of its implementation.

    #include

    class A {

            virtual void f(){};

        public:

            int x;

            A(int in): x(in) {};

    };

    class B: public A {

        public:

            int y;

            B(int in):A(in-1), y(in) {};

    };

    int test(void) {

        int res;

        B b(2);

        A* bp = &b;

        void* vp = dynamic_cast(bp);

        if (  ((A*)vp)->x == 1

           && ((B*)vp)->y == 2

           ) {

            return 1;   // PASS

        } else {

            return 0;   // FAIL

        }

    }

    int main (void) {

        assert (test ());

    }

The code is not complicated, but it has some unnecessary, though well-defined, type-casting. Class A is inherited by class B and both have their own instance variable, x and y respectively. The instantiation of an object of class B, in the second line of the function test, initializes these variables with the values 1 and 2. After two type casts, the if statement verifies these values.

Let us first admire the beauty of the x86-64 code generated by g++ for the function test() with the option -O1:

test():

  mov DWORD PTR [rsp-8], 1

  mov DWORD PTR [rsp-4], 2

  mov rdx, QWORD PTR vtable for B[rip]

  movabs rax, 8589934593

  cmp QWORD PTR [rsp-8+rdx], rax

  sete al

  movzx eax, al

  retA::f():

  rep ret

The compiler knows the layout of the object of type B. With the first two moves, it sets the values of the two variables x and y. Then it compares the values of object b’s fields with the 64-bit immediate 8589934593. In hexadecimal, this value is easier to understand: 0x200000001. The compiler does two comparisons of 32-bit values in one 64-bit comparison! That is a clever move. So far so good.

But now compile the code with -Os, for size optimization. The generated code becomes:

test():

  mov rdx, QWORD PTR vtable for B[rip]

  mov DWORD PTR [rsp-8], 1

  movabs rax, 8589934593

  cmp QWORD PTR [rsp-8+rdx], rax

  sete al

  movzx eax, al

  ret

Do you see what is missing? Somehow, the compiler has forgotten to initialize b's variable y to 2! And thus our test-program fails at the assert.

This is a serious error. Due to the optimization that turns two comparisons into one, the compiler ‘forgets’ that the y field of the object b is used. A def-use analysis after the optimization of the two comparisons then sees no use of y. Therefore the compiler concludes that the initialization of the field y is redundant, and removes it. Is this behavior limited to comparison optimization in combination with some liberal type-casting? Perhaps, but there is no guarantee for that.

It is not the only error. There are also errors in the generated exception handling code when -Os is used. The version of GNU-C shown here is 7.3.0 because that is the current version on Ubuntu. We tried different versions of GNU-C, also for ARM64 targets and not Ubuntu related, and they are all affected. We must conclude that it is not safe to use g++ in combination with the -Os option for 64-bit targets.

Compiler developers run many tests to prevent that errors like these slip through. But compilers are complicated and they have so many configuration options that no compiler supplier can state upfront that your particular use case is verified.

If your application domain is mission-critical or even safety-critical, you need to set up compiler validation for the compiler and for the use cases that are specific to you. If that is beyond your scope, then at least verify that your compiler supplier uses SuperTest. SuperTest provides you with a better chance of staying ahead of compiler errors than any other method that we know of. Let's hope that Space-X does not use g++ with the -Os option.

More Information...

Latest News from Solid Sands

Solid Sands: the day that GNU-C++ -Os broke
Solid Sands: SuperTest helping Graphcore accelerate the future of AI
Solid Sands: SuperTest with native Windows support and requirements traceability for C and C++
Solid Sands: SuperTest suite used by UPMEM to speed up big-data analytics
Solid Sands: SuperTest helps Peloton enhance ‘big-rig’ safety and fuel efficiency
Solid Sands and AbsInt combine tools strengths
Solid Sands: CGtrainer for Code Generator Development

DIN-Rail Embedded Computers from MEN Mikro

The DIN-Rail system from MEN is a selection of individual pre-fabricated modules that can variably combine features as required for a range of embedded Rail Onboard and Rail Wayside applications. The ...


Embedded Graphics Accelerates AI at the Edge

The adoption of graphics in embedded and AI applications are growing exponentially. While graphics are widely available in the market, product lifecycle, custom change and harsh operating environments...


ADLINK Optimizes Edge AI with Heterogeneous Computing Platforms

With increasing complexity of applications, no single type of computing core can fulfill all application requirements. To optimize AI performance at the edge, an optimized solution will often employ a...


Synchronized Debugging of Multi-Target Systems

The UDE Multi-Target Debug Solution from PLS provides synchronous debugging of AURIX multi-chip systems. A special adapter handles the communication between two MCUs and the UAD3+ access device and pr...


Smart Panel Fulfills Application Needs with Flexibility

To meet all requirement of vertical applications, ADLINK’s Smart Panel is engineered for flexible configuration and expansion to reduce R&D time and effort and accelerate time to market. The...


AAEON – Spreading Intelligence in the connected World

AAEON is moving from creating the simple hardware to creating the great solutions within Artificial Intelligence and IoT. AAEON is offering the new solutions for emerging markets, like robotics, drone...


ASIC Design Services explains their Core Deep Learning framework for FPGA design

In this video Robert Green from ASIC Design Services describes their Core Deep Learning (CDL) framework for FPGA design at electronica 2018 in Munich, Germany. CDL technology accelerates Convolutional...


Microchip explains some of their latest smart home and facility solutions

In this video Caesar from Microchip talks about the company's latest smart home solutions at electronica 2018 in Munich, Germany. One demonstrator shown highlights the convenience and functionalit...


Infineon explains their latest CoolGaN devices at electronica 2018

In this video Infineon talks about their new CoolGaN 600 V e-mode HEMTs and GaN EiceDRIVER ICs, offering a higher power density enabling smaller and lighter designs, lower overall system cost. The nor...


Analog Devices demonstrates a novel high-efficiency charge pump with hybrid tech

In this video Frederik Dostal from Analog Devices explains a very high-efficiency charge-pump demonstration at their boot at electronica 2018 in Munich, Germany. Able to achieve an operating efficienc...


Microchip demonstrates a flexible motion control platform at electronica

In this video Marcus from Microchip explains a motion control demonstration at their booth at electronica 2018 in Munich, Germany. The demonstration underscores the ability of the solution to rapidly ...


Infineon goes over their latest SiC devices for automotive systems

In this video an Infineon engineer goes over their latest Silicon Carbide (SiC) devices for automotive systems at electronica 2018 in Munich, Germany. Among the devices described are an inverter for a...


Bertrand Lombardo of Honeywell, Sensing requirements of IoT

Bertrand Lombardo, Sales director for EMEA for Honeywell SIOT discusses future sensing trends in relation to IoT at Electronica 2019 with Alix Paultre. Links to more information: Dynamic Hone...


Analog Devices updates their Silent Switcher technology

In this video an FAE from Analog Devices explains the latest version of their Silent Switcher technology, which addresses noise issues in power systems. He describes a live demonstration in their boot...


Western Digital talks about their automotive-grade memory solutions

In this video Martin Booth from Western Digital talks about the company's memory solutions specifically designed for automotive applications and the harsh environments involved. Systems such as ne...


Picotest demonstrates their latest advanced power test solutions

In this video Steve Sandler from Picotest shows us two of the company's latest test solutions at electronica 2018 in Munich, Germany. The first demo is of a micro-Ohm-resolution power rail measure...


STMicro describes their latest smart 48V DC brushless motor driver board

In this video an engineer from STMIcroelectronics explains a motor-driver board setup based on their L9907 smart power device at electronics 2018 in Munich, Germany. Based on BCD-6s technology. the de...


Microchip shows their newest PolarFire FPGAs at electronica 2018

In this video Microchip shows a one of the demos highlighting the capabilities of their newest low-power PolarFire FPGAs at electronica 2018 in Munich, Germany. The demonstration shown here is a kit f...


Western Digital discusses their memory solutions for Cloud-enabled devices

In this video Ze'ev Paas of Western Digital talks to Alix Paultre of Aspencore Media about their latest memory products at electronica 2018 in Munich, Germany. Depending on the application space, ...


Picotest explains a couple of power test systems at electronica 2018

In this video Steve Sandler from Picotest explains a couple of his power test systems at electronica 2018 in Munich, Germany. The first demonstration shows a micro-Ohm measurement system, and the seco...


wholesale jerseys