3 Replies Latest reply on Oct 31, 2011 7:38 AM by carlos_odonell

    Illegal instruction caused by optimization




      I have a problem to build net-SNMP for ucLinux (-mcpu=53015: mcf53015) using Sourcery toolchains.


      The exact toolchains versions are:

      1) Sourcery G++ Lite 4.4-53 (gcc version 4.4.1)

      2) Sourcery CodeBench Lite 2011.03-97 (gcc version 4.5.2)


      I have a set of tests that passes successfully with no optimization (-O0).

      The same tests fail if the flags -O1 or -O2 are used (even if the stack size is increased few times, just in case).

      Instrumenting the source code makes the test cases to fail in other places.

      The way the crash look like is always different.

      Sometimes the code behaves unexpectedly: some functions return values that are not supposed to be returned.

      But most of the times just an illegal instruction exception is thrown out.


      Breaking down -O1 and -O2 in individual flags gives the following results.

      If any of the following flags is specifiied, then the tests crash (the behavior does not vary a lot, it looks like the same problem is hit every time).

      -fomit-frame-pointer (included in -O1)

      -fauto-inc-dec (included in -O1)

      -ftree-forw-prop (included in -O1, 4.5.2 only)

      -fcrossjumping  (included in -O2)

      -fcse-follow-jumps (included in -O2)

      There are more -O2 flags involved, I just gave up to find them all.


      What can be wrong with -fauto-inc-dec???

      I double checked few places of the binary where this flag makes changes.

      The changes look just fine.


      Could you, please, help me to identify the cause of this problem?

      Are there any updates available for the toolchain, that can solve it?

      What would you recommed to do to continue the investigation process?


      Thank you

      Roman Kuzmenko

        • 1. Re: Illegal instruction caused by optimization

          Have you debugged your code with the debugger to see what happens?



          But most of the times just an illegal instruction exception is thrown out.



          If you can catch this under the debugger and see if the instruction is actually in the binary, then we can talk more constructively about the problem e.g. compiler generates invalid instruction for your target.


          I would suggest you start by debugging the application.




          • 2. Re: Illegal instruction caused by optimization

            Hi Carlos,


            Debugging shows that different optimization flags make different stack sizes.

            The unoptimized code gets a bigger stack and, thus, works good.


            Well, the stack size is always the same.

            But it looks like the stack end is aligned to the end of the page.

            Thus, the space available for the stack depends on the the page offset of the end of the bss segment.


            So the problem was that the stack size is not sufficient.

            But this kind of problem is very hard to investigate if the generated code does not check for available stack space.


            I made an assumption that the following compiler flags are sufficient to generate a 'left-stack-space' aware code:

            "-fstack-check -fstack-limit-symbol=_ebss".

            But it does not look like it has any effect on the code generated by my toolchain for this platform.

            How do I make the code aware of the free stack space?


            BTW: the utility "flthdr" does not complain if you specify stack size equal to, for example, "8K",

            but the outcome is not what one should expect.




            • 3. Re: Illegal instruction caused by optimization

              The stack checking support in the compiler only serves to detect when you run out of stack and allow you to recover from that situation, but this won't help if you consistently allocate more stack than you have.


              The use of alloca, and malloc will both return error codes when they run out of stack and they know exactly where the limit lies, but you must check their return values.


              The ColdFire port doesn't have a special stack checking implementation (for example one that checks to see if the function call use of the stack might overflow the stack) and uses the default probing mechanism which means that the compiler may probe for stack overflow once ever 2^12 instruction bytes, which in the case of a small device might be once or not at all depending on the layout.


              Therefore for a small ColdFire part there is no easy way, except through manual checking, to see if you've overflowed the stack at any given point in time.


              You can do this yourself by using `-finstrument-functions` and writing a hook function that checks to see where the stack is at during entry and exit of a function.


              Hopefully that helps you out.