Thread: Illegal Instruction at perfectly fine Code

  1. #1
    Registered User
    Join Date
    Feb 2011
    Posts
    11

    Illegal Instruction at perfectly fine Code

    Hey,

    I have been having a strange problem for the last couple of days. I create code with a native code compiler (the code should be valid checked it a couple of times) and then I want to execute that Code. I am using a PowerPC microcontroller with some kind of linux OS. So I am running a C program where I have a Byte array containing the native Code. Then I do the usual trick where I create a function pointer to that array and call that function. When I debug/start this program I have the following behaviour:

    1. Debug with Breakpoint at native code call and single stepping:
    I start at the function call and step through my native Code operatior for operation. My crated native code is executed perfectly everything is fine.

    2. Debug without Breakpoint
    Program halts at the first instruction (depending on native code, sometimes a later instructions but always another instruction i.e. not alway LD or ST or whatever) with the error SIGILL (Illegal Instruction)

    3. Executing of binary file
    Program terminates with SIGILL

    I am using GDBServer for remote debugging. Additionally at the second case, I checked the instruction I checked the registers and I checked the memory everything seems to be ok. I can not figure out why my program works with single stepping but not when I execute it normally...

    Also here is part of my code, I know it is not much but that is basically what I do. I have a prepared NC array which represents a C function (the code works when I execute it as Assembler instructions).

    Code:
    LZSBYTE (*NC_fct)(LZSDWORD, LZSDWORD, LZSDWORD);
    LZSBYTE *AnfNS;
    
    ...
    
    NC_fct = (LZSBYTE(*)()) AnfNS;
    bRetCode = (*NC_fct)((LZSDWORD) pSegTab_l, (LZSDWORD) pAdrDS, (LZSWORD) hChildInst_p);
    Here is the input NC Array, which basically translates to i = 1; i = i + 1;

    Code:
    li r0, 1
    andi. r0, r0, 65535
    sth r0, 8(r4)
    lhz r0, 8(r4)
    li r10, 1
    andi. r10, r10, 65535
    extsh r0, r0
    extsh r10, r10
    addo. r0, r0, r10
    andi. r0, r0, 65535
    sth r0, 8(r4)
    li r3, 0
    blr
    Help would be very much appreciated =D

  2. #2
    Registered User
    Join Date
    Feb 2011
    Posts
    11
    As it turns out, the problem seems to be the memory address in which the code is stored. I am going to save you the details but if I copy my NC to a certain memory address and then again try to execute it then my program works fine.

    I know that there is something like a never execute bit on most microcontroller which makes it impossible to execute code that is stored at certain memory addresses. This is done to protect the operating system. Does anybody know how I can remove that security mechanism? I am using a PowerPC MPC5200 with a linux on it.

    Again help would be very much appreciated =D

  3. #3
    Registered User
    Join Date
    May 2010
    Posts
    4,633
    I know that there is something like a never execute bit on most microcontroller which makes it impossible to execute code that is stored at certain memory addresses. This is done to protect the operating system. Does anybody know how I can remove that security mechanism? I am using a PowerPC MPC5200 with a linux on it.
    This is not a microcontroller issue but a Linux issue. Linux will not allow your to write to memory that is not assigned to your program (Linux runs in protected mode). You can not assume that the memory address that you see in your program maps to the actual physical memory (Linux uses virtual memory).

    Jim

  4. #4
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,656
    Quote Originally Posted by man page
    NAME
    mprotect - set protection on a region of memory

    SYNOPSIS
    #include <sys/mman.h>

    int mprotect(const void *addr, size_t len, int prot);
    Use this to mark your memory as being executable.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  5. #5
    Registered User
    Join Date
    Oct 2008
    Location
    TX
    Posts
    2,059
    Quote Originally Posted by m00ni View Post
    As it turns out, the problem seems to be the memory address in which the code is stored. I am going to save you the details but if I copy my NC to a certain memory address and then again try to execute it then my program works fine.


    I know that there is something like a never execute bit on most microcontroller which makes it impossible to execute code that is stored at certain memory addresses. This is done to protect the operating system. Does anybody know how I can remove that security mechanism? I am using a PowerPC MPC5200 with a linux on it.

    Again help would be very much appreciated =D
    A possible cause could be that you're trying to load instructions on the stack and on most OSes the stack is not executable.

  6. #6
    Banned
    Join Date
    Aug 2010
    Location
    Ontario Canada
    Posts
    9,547
    Ummm... does your compiler for that PIC not support inline assembly?

    Seems to me you'd save yourself a lot of trouble if you created an _asm routine for that code and called it like a regular C function.

  7. #7
    Registered User
    Join Date
    Feb 2011
    Posts
    11
    Hey,

    Thanks for all the already very helpful advice. Basically I integrated an Native Code Compiler into a Runtime Environment which is executed on the powerpc linux microcontroller. so when a program is downloaded onto the microcontroller the source is a intermediate code representation and within the runtime environment I translate that intermediate code into native code and then execute it. So what I do is basically calculate how much memory I need to store all the native code, then create a big enough byte array and fill it with the native code.

    I have to use the runtimeenvironment malloc and free functions, they work a bit different then normal malloc, on initialization of the RTE it reserves a lot of memory and then when a RTEMalloc is called it manages that reserved memory. But I do not think that I am storing the code on the stack =D

    I am going to get started on the advice you gave me, I hope I can fix it today =D Thx =D

  8. #8
    Registered User
    Join Date
    Feb 2011
    Posts
    11
    I tryed the advice with mprotect:

    Code:
    bRetCode = mprotect(pNativeCodeArray, wNativeCodeArraySize, PROT_EXEC);
    Sadly it does not help at all, I think that might have something to do with mprotext returning 0xff instead of 0 =D

  9. #9
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,656
    > I think that might have something to do with mprotext returning 0xff instead of 0
    I think looking at errno would tell you more than "it doesn't work".
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  10. #10
    Registered User
    Join Date
    Feb 2011
    Posts
    11
    yep just did that and figured out where my problem was. The man page I looked at sayd I can specify any mem address, but as it turns out I need to align in with mempage size. So I have done that, but sadly even after marking my memory as executable I receive SIGILL at the first instruction... So I am completely lost again.

    I just don't get it everything is finde when I look at the debug information...

  11. #11
    Registered User
    Join Date
    Feb 2011
    Posts
    11
    Is there a way to mark memory as Read/Write/Executable and not only one of them? Because mprotect replaces the protection and does not add them up, so depending on where exactly the pointer is a lot of memory is executable and not anymore writable/readable.

  12. #12
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,656
    I think normally, you would allocate a single large (a multiple of page size) block for your code and manage the permissions on that using some wrapper functions.

    Memory with rwx permissions is going back to the bad old days of self modifying code.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  13. #13
    Registered User
    Join Date
    Oct 2008
    Location
    TX
    Posts
    2,059
    Quote Originally Posted by m00ni View Post
    Hey,

    Thanks for all the already very helpful advice. Basically I integrated an Native Code Compiler into a Runtime Environment which is executed on the powerpc linux microcontroller. so when a program is downloaded onto the microcontroller the source is a intermediate code representation and within the runtime environment I translate that intermediate code into native code and then execute it. So what I do is basically calculate how much memory I need to store all the native code, then create a big enough byte array and fill it with the native code.
    Are you generating hex files that are downloaded into the chip thro' a programmer?
    Describe the exact process you're using to burn the code into the microcontroller.
    Quote Originally Posted by m00ni View Post
    I have to use the runtimeenvironment malloc and free functions, they work a bit different then normal malloc, on initialization of the RTE it reserves a lot of memory and then when a RTEMalloc is called it manages that reserved memory. But I do not think that I am storing the code on the stack =D

    I am going to get started on the advice you gave me, I hope I can fix it today =D Thx =D
    If you are malloc()'ing, the code is in the data segment, which by default is not executable.
    Use mprotect() as stated or detail the process you're using as it ain't clear what you're trying.

  14. #14
    Registered User
    Join Date
    Feb 2011
    Posts
    11
    Hey,

    Alright I am going to describe it in more deatail now. I have a PowerPC microcontroller with some kind of linux on it. On this microcontroller runs a RTE which is written in C. Now the normal way that we use that microcontroller is the following: On the PC we have a software wich allows us to write code with 5 different programming languages for microcontroller, the programs will then get translated into an immediate code representation and native code if requested before the compile process. When I transfer the code to the microcontroller the RTE will download the code store it somewhere and then execute it. So when I download native code into the RTE and execute it (the memory where the native code is stored is allocated with the RTEMALLOC function which is a bit different then normal malloc, i ll explain a bit further down). So after the download I have native code and intermediate code within the RTE. Normally the native code is now executed as the program for the microcontroller. But in order to get more performance out of the code I am trying to implement a native code compiler which runs whithin the RTE, that means I read the intermediate code and compile it again to native code, although this time I link data and code, which means I do not need so many instructions to calculate memory addresses and call destinations for example. This should speed up the execution of my native code. So after the compile process I have 3 kinds of code on the microcontroller: Intermediate code, which nobody cares for anymore after the compile process, native code, which has been downloaded to the mc, and native code which has been created locally.
    So basically only the two kinds of native code are interesting, for testing I use code which results in the same native code for both, to eliminate mistakes from compiling. So the instructions in the two native code arrays are completely identical, the only difference is where they are stored.
    Then I do the usual thing with getting a function pointer on one of the arrays and execute it. When I do this with the downloaded native code everything works perfectly, if I do it with my compiled native code i get sigill at some point, mostly at first instruction. The address difference between the two arrays is not really big, it is like 0x10069xxx and 0x1006Axxx.

    So how does the malloc work on this system: When the RTE is started it allocates a huge array of memory staticly. And then just hands out bits of that memory to everything that requests memory. So both arrays get their memory the exact same way, but one I can execute the other I can't. And yes if I copy my locally crated nc to the downloaded nc position i can execute my nc as long it is in the same memory address range (calls and jumps sometimes jump to other places in the memory because the code for functions is stored in different arrays not the same)

    So I hope you now know what I am doing =D I really could use some help, I spend already two weeks on that stupid problem and the deadline of my thesis is getting closer and closer =D

    EDIT:
    Code:
    mprotect(AnfNS - ((LZSDWORD)AnfNS % 4096), wNsSize + ((LZSDWORD)AnfNS % 4096), PROT_EXEC);
    
    	NC_fct = (LZSBYTE(*)()) AnfNS;
    	bRetCode = (*NC_fct)((LZSDWORD) pSegTab_l, (LZSDWORD) pAdrDS, (LZSWORD) hChildInst_p);
    AnfNS is the pointer to my native code and wNsSize is the size of the array. This results in Segmentation fault, probably because I am writing the result from my nc computations back in the memory and the memory is now executable only. I will try to maybe rewrite the MemAlloc for my RTE so that code and data gets allocated in different places. But strangely the memory where the downloaded nc is stored seems to be executable without mprotect...
    Last edited by m00ni; 02-10-2011 at 03:23 AM.

  15. #15
    Registered User
    Join Date
    Feb 2011
    Posts
    11
    My very minimalistic example works fine now, but as soon as the created code becomes larger I get Sigill in the middle of execution. Is there something wrong with my memory range calculation for mprotect?

    To align with page size I do this to calculate starting address: pointer - pointer % 4096
    then I do this for length: array size + pointer % 4096

    That should cover the whole array, shouldn't it?

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. dynamic array
    By mouse666666 in forum C Programming
    Replies: 36
    Last Post: 04-11-2010, 02:27 AM
  2. Beginner: What is wrong with my code? It seems fine!
    By shivdude in forum C Programming
    Replies: 10
    Last Post: 08-03-2009, 03:36 PM
  3. Explain this C code in english
    By soadlink in forum C Programming
    Replies: 16
    Last Post: 08-31-2006, 12:48 AM
  4. Replies: 4
    Last Post: 01-16-2002, 12:04 AM
  5. Big Code, Little Problem
    By CodeMonkey in forum Windows Programming
    Replies: 4
    Last Post: 10-03-2001, 05:14 PM