Search code examples
cgcccmdmicrocontrollertoolchain

LPCXpresso error CreateProcess: No such file or directory


I know there are multiple questions regarding this subject, but they did not help. When trying to compile, whatever, I keep getting the same error:

arm-none-eabi-gcc.exe: error: CreateProcess: No such file or directory

I guess it means that it can not find the compiler. I have tried tweaking the path settings

C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\nxp\LPCXpresso_7.6.2
326\lpcxpresso\tools\bin;

Seems to be right?

I have tried using Sysinternals process monitor I can see that a lot of arm-none-eabi-gcc.exe are getting a result of name not found but there are a lot of successful results too.

I have also tried reinstalling the compiler and the LPCXpresso, no luck.

If i type arm-none-eabi-gcc -v i get the version, so it means its working but when i am trying to compile in CMD like this arm-none-eabi-gcc led.c i get the same error as stated above

arm-none-eabi-gcc.exe: error: CreateProcess: No such file or directory

Tried playing around more with PATH in enviroments, no luck. I feel like something is stopping LPCXpresso from finding the compiler The only Antivirus this computer has is Avira and i disabled it. I also allowed compiler and LPCXpresso through the firewall I have tried some more things, i will add it shortly after trying to duplicate the test.


Solution

  • It seems your problem is a happy mess with Vista and GCC. Long story short, a CRT function, access, has a different behavior on Windows and Linux. This difference is actually mentioned on Microsoft documentation, but the GCC folks didn't notice. This leads to a bug on Vista because this version of Windows is more strict on this point.

    This bug is mentioned here : https://gcc.gnu.org/bugzilla/show_bug.cgi?id=33281

    I have no proof that your problem comes from here, but the chances are good.

    The solutions :

    1. Do not use Vista
    2. Recompile arm-none-eabi-gcc.exe with the flag -D__USE_MINGW_ACCESS
    3. Patch arm-none-eabi-gcc.exe

    The 3rd is the easiest, but it's a bit tricky. The goal is to hijack the access function and add an instruction to prevent undesired behavior. To patch your gcc, you have two solutions : you upload your .exe and I patch it for you, or I give you the instructions to patch it yourself. (I can also patch it for you, then give the instructions if it works). The patching isn't really hard and doesn't require advanced knowledge, but you must be rigorous.

    As I said, I don't have this problem myself, so I don't know if my solution really works. The patch seems to be working for this problem.

    EDIT2:

    The exact problem is that the linux access have a parameter flag to check whether a file is executable. The Windows access cannot check for this. The behavior of most Windows versions is just to ignore this flag, and check if the file exists instead, which will usually give the same behavior. The problem is that Vista doesn't ignore this, and whenever the access is used to check for executability, it will return an error. This lead to GCC programs to think that some executables are not here. The patch induced by -D__USE_MINGW_ACCESS, or done manually, is to delete the flag when access is called, thus checking for existence instead just like other Windows versions.


    EDIT:

    The patching is actually needed for every GCC program that invokes other executables, and not only gcc.exe. So far there is only gcc.exe and collect2.exe.

    Here are the patching instruction :

    1. Backup your arm-none-eabi-gcc.exe.
    2. Download and install CFF Explorer (direct link here).
    3. Open arm-none-eabi-gcc.exe with CFF Explorer.
    4. On the left panel, click on Import Directory.
    5. In the module list that appears, click on the msvcrt.dll line.
    6. In the import list that appears, find _access. Be careful here, the list is long, and there are multiple _access entries. The last one (the very last entry for me) is probably the good one.
    7. When you click on the _access line, an address should appear on the list header, in the 2nd column 2nd row, just below FTs(IAT). Write down that address on notepad (for me, it is 00180948, it may be different). I will refer to this address as F.
    8. On the left panel, click on Address Converter.
    9. Three fields should appear, enter address F in the File Offset field.
    10. Write down on notepad a 6 bytes value : the first two bytes are FF 25, the last 4 are the address that appeared in the VA field, IN REVERSE. For example, if 00586548 appeared in the VA field, write down FF 25 48 65 58 00 (spaces added for legibility). I will refer to this value as J. This value J is the instruction that jumps to the _access function.
    11. On the left panel, click on Section Headers.
    12. In the section list that appeared on the right, click on the .text line (the .text section is where the code resides).
    13. In the editor panel that appeared below, click on the magnifier and, in the Hex search bar, search for a series of 11 90 (9090909090..., 90 is NOP in assembly). This is to find a code cave (unused space) to insert the patch, which is 11 bytes long. Once you found a code cave, write down the offset of the first 90. The exact offset is displayed on the very bottom as Pos : xxxxxxxx. I will refer to this offset as C.
    14. Use the editor to change the sequence of 11 90 : the first 5 bytes are 80 64 E4 08 06. These 5 bytes are the instruction that prevents the wrong behavior. The last 6 bytes are the value J (edit the next 6 bytes to J, ex. FF 25 48 65 58 00), to jump back to the _access function.
    15. Click on the arrow icon (Go To Offset) a bit below, and enter 0, to navigate to the beginning of the file.
    16. Use the Hex search bar again to search for value J. If you find the bytes you just modified, skip. The J value you need is located around many value containing FF 25 and 90 90. That is the DLL jump table. Write down the offset of the value J you found (offset of the first byte, FF). I will refer to this offset as S. Note 1: If you can't find the value, maybe you picked the wrong _access in step 6, or did something wrong between step 6 to 10. Note 2: The search bar doesn't loop when it hit the end; go to offset 0 manually to re-find.
    17. Use a hexadecimal 32-bit 2-complement calculator (like this one : calc.penjee.com) to calculate C - S - 5. If your offset C is 8C0 and your offset S is 6D810, you must obtain FF F9 30 AB (8C0 minus 6D810, minus 5).
    18. Replace the value J you found in the file (at step 16) by 5 bytes : the first byte is E9, the last 4 are the result of the last operation, IN REVERSE. If you obtained FF F9 30 AB, you must replace the value J (ex: FF 25 48 65 58 00) by E9 AB 30 F9 FF. The 6th byte of J can be left untouched. These 5 bytes are the jump to the patch.
    19. File -> Save

    Notes : You should have modified a total of 16 bytes. If the patched program crash, you did something wrong. Even if it doesn't work, this patch can't induce a crash.

    Let me know if you have difficulties somewhere.