用UCLIBC交叉编译PHP

这是一个REPOST,以前的岗位GOTclosures,搬到SERVERFAULT和再次closures。 我认为这个post是一个有效的stackoverflow问题,因为我认为它是由一些automake /编译/链接错误引起的。 这是一个编程问题,而不是服务器pipe理员问题。

交叉编译PHP

https://serverfault.com/questions/418521/cross-compile-php

开始发布

我已经下载了PHP 5.4.0源代码,将其解压缩并移入源文件夹。

我做了一个configuration:

./configure --build=x86_64-unknown-linux-gnu --host=arm-linux-uclibcgnueabi --prefix=/usr/arm/www CC="arm-linux-uclibcgnueabi-gcc --sysroot=/toolchains/gnu_cortex-a9_tools/" --disable-libxml --disable-dom --without-iconv --without-openssl --disable-simplexml --disable-xml --disable-xmlreader --disable-xmlwriter --without-pear --without-sqlite3 --disable-pdo --without-pdo-sqlite --disable-phar --with-config-file-path=/etc/ 

其次是

 make 

没有错误,一切运行良好。 接下来我做一个make install。

 make install 

再次,一切运行良好。 我将它移动到目标平台并运行

 /usr/arm/www/bin/php -v PHP 5.4.0 (cli) (built: Aug 15 2012 16:07:41) Copyright (c) 1997-2012 The PHP Group Zend Engine v2.4.0, Copyright (c) 1998-2012 Zend Technologies 

我用我的web服务器testing一个简单的主页,直接用php。

 <?php echo "hello" ?> # php index.php hello 

它按预期工作。 接下来我testing:

 <?php $output = shell_exec('ls -lart'); echo "<pre>$output</pre>"; ?> 

哦,noes〜

 # php shell.php Segmentation fault 

我酝酿另一个脚本:

 #!/bin/php <?php echo "hello"; $handle = fopen("info.txt", "r"); echo $handle; ?> 

同样的结果:

 # php index.php helloSegmentation fault 

我有一个php.ini?

 # /usr/arm/www/bin/php --ini Configuration File (php.ini) Path: /etc/ Loaded Configuration File: /etc/php.ini 

是的,没有禁用的function。 testingstrace / usr / arm / www / bin / php index.php

 lstat("/srv/www/info.txt", {st_mode=S_IFREG|0644, st_size=20, ...}) = 0 open("/srv/www/info.txt", O_RDONLY) = 3 fstat(3, {st_mode=S_IFREG|0644, st_size=20, ...}) = 0 lseek(3, 10, SEEK_CUR) = 0 --- SIGSEGV (Segmentation fault) @ 0 (0) --- +++ killed by SIGSEGV +++ 

文件info.txt存在,它获得了读/写的权限。

testingstrace / usr / arm / www / bin / php shell.php

 fcntl64(3, F_GETFL) = 0 (flags O_RDONLY) ioctl(3, SNDCTL_TMR_TIMEBASE or TCGETS, 0x7e31fddc) = -1 EINVAL (Invalid argument) vfork() = 3324 close(4) = 0 fstat(3, {st_mode=S_IFIFO|0600, st_size=0, ...}) = 0 read(3, "total 24\n-rw-rw-r-- 1 1001 "..., 8192) = 468 read(3, ""..., 8192) = 0 --- SIGCHLD (Child exited) @ 0 (0) --- close(3) = 0 wait4(3324, [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], 0, NULL) = 3324 --- SIGSEGV (Segmentation fault) @ 0 (0) --- +++ killed by SIGSEGV +++ 

如果我通过gdb运行index.php,它会给我:

 Starting program: /usr/arm/www/bin/php index.php hello Program received signal SIGSEGV, Segmentation fault. zend_do_fcall_common_helper_SPEC (execute_data=0x2ac7a040) at /home/maiden/Downloads/php-5.4.0/Zend/zend.h:391 391 /home/maiden/Downloads/php-5.4.0/Zend/zend.h: No such file or directory. in /home/maiden/Downloads/php-5.4.0/Zend/zend.h 

gdb给了我这个从shell.php启动程序:/ usr / arm / www / bin / php shell.php

 Program received signal SIGSEGV, Segmentation fault. zend_do_fcall_common_helper_SPEC (execute_data=0x2ab76040) at /home/maiden/Downloads/php-5.4.0/Zend/zend.h:391 391 in /home/maiden/Downloads/php-5.4.0/Zend/zend.h 

zend.h位于/ usr / arm / www / include / php / Zend /显然在交叉编译时出错了。 我错过了什么? 我没有find任何configuration标志来纠正这一点,并创build一个符号链接到所需的位置删除gdb输出,但PHP仍然segfaults。

谢谢你的帮助!

更新:

 # valgrind php test.php ==2181== Memcheck, a memory error detector ==2181== Copyright (C) 2002-2012, and GNU GPL'd, by Julian Seward et al. ==2181== Using Valgrind-3.8.0 and LibVEX; rerun with -h for copyright info ==2181== Command: php test.php ==2181== ==2181== Conditional jump or move depends on uninitialised value(s) ==2181== at 0x4004EC8: ??? (in /lib/ld-uClibc-0.9.30-nptl.so) ==2181== ==2181== Invalid read of size 4 ==2181== at 0x4004D48: _dl_get_ready_to_run (in /lib/ld-uClibc-0.9.30-nptl.so) ==2181== Address 0x7d4cc304 is just below the stack ptr. To suppress, use: --workaround-gcc296-bugs=yes ==2181== ==2181== Invalid read of size 4 ==2181== at 0x48C348C: __uClibc_main (in /lib/libuClibc-0.9.30-nptl.so) ==2181== Address 0x7d4cc554 is just below the stack ptr. To suppress, use: --workaround-gcc296-bugs=yes ==2181== ==2181== Invalid write of size 4 ==2181== at 0x233010: __eqdf2 (ieee754-df.S:1120) ==2181== Address 0x7d4cb0bc is just below the stack ptr. To suppress, use: --workaround-gcc296-bugs=yes ==2181== Warning: shell_exec(): Unable to execute 'ls -lart' in /test.php on line 3 ==2181== Invalid read of size 4 ==2181== at 0x1FF1AC: zend_do_fcall_common_helper_SPEC (zend.h:391) ==2181== by 0x1F3D17: execute (zend_vm_execute.h:410) ==2181== by 0x18B217: zend_execute_scripts (zend.c:1279) ==2181== by 0x1365BB: php_execute_script (main.c:2473) ==2181== by 0x22B52B: do_cli (php_cli.c:988) ==2181== by 0x22BD4B: main (php_cli.c:1364) ==2181== Address 0x8 is not stack'd, malloc'd or (recently) free'd ==2181== Segmentation fault 

UPDATE2

用memcheck重新运行valgrind,得到了与以前相同的输出,但是这是新的:

 php: can't resolve symbol '__libc_freeres' 

UPDATE3

虽然valgrind失败了我,我继续与gdb,我创build文件夹/ home / maiden / .. etc在我的目标系统上,并复制我的php / include文件夹的内容,并重新运行gdb。 现在我得到这个错误消息:

 (gdb) run index.php Starting program: /bin/php index.php hello Program received signal SIGSEGV, Segmentation fault. zend_do_fcall_common_helper_SPEC (execute_data=0x2ab34040) at /home/maiden/Downloads/php-5.4.5/Zend/zend.h:391 warning: Source file is more recent than executable. 391 return --pz->refcount__gc; 

这与sixeightzero昨天在评论中写的非常相似。 我现在已经尝试了PHP版本5.3.5,5.4.0,5.4.5所有相同的错误。

UPDATE4

我为glibc下载了一个新的工具链,用glibc交叉编译了一个新的busybox,创build了一个chroot jail,用glibc交叉编译的php而不是uclibc,并在我的uclibc盒子的chroot监狱里testing了它,它起作用了! 但我仍然需要让PHP在我的uclibc环境中工作….

我会检查uClibc的configure.log来查看是否启用了ARCH_USE_MMU和fork。 如果不是vfork被可能被shell_exec使用的fork替换。 vfork的主要问题是,父母和孩子使用相同的内存空间,导致奇怪的崩溃。