Lua compiled scripts on Mac OS X - Intel vs. PPC

Used by Lua 5.0 in Mac OS X universal binary application for several years. Lua scripts are compiled using luac, and compiled scripts are bundled with the application. They worked great at Tiger and Leopard, Intel or PPC.

To avoid problems with the library at the time, I just added the Lua src tree to my Xcode project and compiled as is, no problem.

It's time to upgrade to a more modern version of Lua, so I replaced the original tree with 5.1.4. I rebuilt luac using make macosx (Leopard runs on Intel on the computer).

Uncompiled scripts work correctly in Tiger and Leopard, Intel and PPC, as always.

However, now compiled scripts do not load on PPC machines.

So, I rebuilt luac with the ansi flag and recompiled my scripts. The same mistake. Likewise, the generic build flag did not cause any joy.

Can anyone advise what I can do next?

+4
source share
6 answers

Compiled Lua scripts are pretty much the source bytecode dumped after the short header. The header documents some of the platform properties used to compile the bytecode, but the loader only verifies that the current platform has the same properties.

Unfortunately, this creates problems when loading bytecode compiled on another platform, even if it was compiled with the same version of Lua. Of course, scripts compiled by different versions of Lua cannot work, and since the Lua version number is included in the bytecode header, an attempt to load them will catch the kernel.

The simple answer is simply compiling the scripts. If Lua compiles the script itself, you only need to worry about possible version mismatches between the Lua kernels in your different builds of your application, and it's not difficult.

In fact, support for full cross-compatibility for compiled bytecode is not easy . In this letter, Mike Pall identified the following issues:

  • Endianess: swap output as needed.

  • sizeof(size_t) , affects huge string constants: check overflow when downgrading.

  • sizeof(int) , affects MAXARG_Bx and MAXARG_sBx : check for overflow when downgrading.

  • typeof(lua_Number) : easy in C, but only when the host and target adhere to the same FP standard; accuracy loss during updating (rare case); warn about non-integer numbers when downgrading to int32 .

From all the discussions I've seen about this issue on the mailing list, I see two possible viable approaches, assuming you don't want to consider sending unrelated Lua scripts.

The first will be the correction of the byte order when loading compiled scripts. This turns out to be simpler than you expected, since it can be done by replacing the low-level function that reads the script file without recompiling the kernel itself. In fact, this can even be done in pure Lua by providing the chunk reader the lua_load () function. This should work as long as the only compatibility issue with your platforms is the byte order.

Secondly, to fix the kernel itself, use the general view for compiled scripts on all platforms. This is described as possible by Luiz Henrique de Figueiredo :

.... I am convinced that the best way is to order bytes or cross-compile third-party dump / chain pairs. the ldump.c and lundump.c files are completely replaceable; they export a single, well-defined, entry point. the format of precompiled pieces is not sacred at all; you can use any format as long as ldump.c and lundump.c agree on this. (For example, Lake Richie's consideration of writing a text format for precompiled chunks.) ....

Personally, I would recommend taking seriously not to pre-compile scripts and, thus, completely avoid problems with platform portability.

Edit: I updated the bytecode header description thanks to lhf comments. I have not read this part of the Lua source yet, and I probably should have checked it before I was pretty sure what information is in the header or not.

Here is a fragment of lundump.c , which forms a copy of the header corresponding to the working platform, for comparison with the loaded bytecode. It is simply compared to memcmp() to exactly match the file header, so any mismatch causes the loader ( luaU_undump() ) to reject the file.

 /* * make header */ void luaU_header (char* h) { int x=1; memcpy(h,LUA_SIGNATURE,sizeof(LUA_SIGNATURE)-1); h+=sizeof(LUA_SIGNATURE)-1; *h++=(char)LUAC_VERSION; *h++=(char)LUAC_FORMAT; *h++=(char)*(char*)&x; /* endianness */ *h++=(char)sizeof(int); *h++=(char)sizeof(size_t); *h++=(char)sizeof(Instruction); *h++=(char)sizeof(lua_Number); *h++=(char)(((lua_Number)0.5)==0); /* is lua_Number integral? */ } 

As you can see, the header is 12 bytes long and contains a signature (4 bytes, " <esc>Lua "), version and format codes, a byte flag for judging, sizes of int , size_t , Instruction and lua_Number and a flag indicating whether lua_Number integral type.

This allows most of the differences in the platform to be caught, but does not try to catch every way that the platforms can differ.

I still adhere to the recommendations made above: firstly, ship compiled sources; or second, configure ldump.c and lundump.c to save and load the common format, with the additional note that any custom format should override the LUAC_FORMAT byte of the header so as not to be confused with the stock byte code format.

+13
source

You might want to use a fixed byte code handler that supports various content. See this .

+3
source

I would comment on the RBerteig post, but I apparently don't have enough reputation to do this. Working to make LuaRPC speed up with Lua 5.1.x and to work with built-in objects, I modified the sources ldump.c and lundump.c to make them more flexible. The nested Lua project (eLua) already had some of the patches that you can find in the Lua list, but I added a bit more to make lundump more convenient for scripts compiled on different architectures. It also supports cross-compilation support so that you can create for purposes other than the main system (see Luac.c in the same directory as the links below).

If you are interested in checking for changes, you can find them in the original eLua repository: http://svn.berlios.de/wsvn/elua/trunk/src/lua/lundump.c http://svn.berlios.de/wsvn /elua/trunk/src/lua/lundump.h http://svn.berlios.de/wsvn/elua/trunk/src/lua/ldump.c

Standard Disclaimer: I do not claim that modifications are ideal or work in any situation. If you use it and find something broken, I would be happy to hear about it so that it can be fixed.

+3
source

Lua bytecode is not portable. You must send the source scripts with your application.

If the download size is a problem, they are usually shorter than the bytecode form.

If intellectual property is a concern, you can use a code obfuscator, and keep in mind that Lua bytecode disassembly is all that complicated.

If boot time is a problem, you can pre-copy the sources locally to your installation script.

+1
source

I assume that you compiled the scripts on the Intel box.

Compiled scripts are inactive. If you really want to precompile the scripts, you need to include two versions of each compiled script: one for Intel and one for PPC. Your application will have to interrogate which program is running and use the correct compiled script.

0
source

I do not have enough reputation for comments, so I have to provide this as an answer, although this does not correspond to the answer to the question asked. Unfortunately.

There is a Lua obfuscator here:

http://www.capprime.com/CapprimeLuaObfuscator/CapprimeLuaObfuscator.aspx

Full disclosure: I am the author of the obfuscator, and I know that this is not ideal. Feedback is encouraged and encouraged (the feedback page is available on the page above).

0
source

Source: https://habr.com/ru/post/1286793/


All Articles