Почему мой кросс-компилированный двоичный файл CGO не запускается на Raspberry Pi (Raspbian)?

Когда я компилирую следующий фрагмент кода (ссылка на игровую площадку):

package main

/*
#cgo LDFLAGS: -lbluetooth

#include <bluetooth/bluetooth.h>
#include <bluetooth/hci.h>
#include <bluetooth/hci_lib.h>
*/
import "C"

func main() {
        C.hci_get_route(nil)
}

…используя эти переменные среды:

CC=arm-linux-gnueabihf-gcc
CGO_ENABLED=1
GOARCH=arm
GOARM=6

Я получаю двоичный файл размером 1,6 МБ, который:

  • работает на моем ODROID-C1 (ARMv7, под управлением Arch, с archlinuxarm.org), но
  • не работает на моем Raspberry Pi B+ (ARMv6, под управлением Raspbian, с сайта raspberrypi.org).

Когда я запускаю его на Pi, я получаю «Segmentation fault».

Когда я запускаю его с этими переменными среды:

LD_PRELOAD=/lib/arm-linux-gnueabihf/libSegFault.so
SEGFAULT_USE_ALTSTACK=1

Я получаю этот вывод:

*** Segmentation fault
Register dump:
 R0: 00000000   R1: 00000001   R2: bebf37f4   R3: bebf37fc
 R4: 00000000   R5: 00000000   R6: 00010c59   R7: 00000000
 R8: 00000000   R9: 00000000   SL: b6f33000   FP: 00000000
 IP: 0000004f   SP: bebf37ec   LR: 00010c6b   PC: 0005d7f4
 CPSR: 40000030
 Trap: 0000000e   Error: 00000817   OldMask: 00000000
 Addr: 00000001
Backtrace:
Memory map:
00010000-00125000 r-xp 00000000 b3:02 16193      /home/pi/test
00135000-0013b000 rw-p 00115000 b3:02 16193      /home/pi/test
0013b000-0014a000 rw-p 00000000 00:00 0 
0026b000-00290000 rw-p 00000000 00:00 0          [heap]
b6d53000-b6d73000 r-xp 00000000 b3:02 16080      /lib/arm-linux-gnueabihf/libgcc_s.so.1
b6d73000-b6d7a000 ---p 00020000 b3:02 16080      /lib/arm-linux-gnueabihf/libgcc_s.so.1
b6d7a000-b6d7b000 rw-p 0001f000 b3:02 16080      /lib/arm-linux-gnueabihf/libgcc_s.so.1
b6d7b000-b6e9f000 r-xp 00000000 b3:02 4254       /lib/arm-linux-gnueabihf/libc-2.13.so
b6e9f000-b6ea6000 ---p 00124000 b3:02 4254       /lib/arm-linux-gnueabihf/libc-2.13.so
b6ea6000-b6ea8000 r--p 00123000 b3:02 4254       /lib/arm-linux-gnueabihf/libc-2.13.so
b6ea8000-b6ea9000 rw-p 00125000 b3:02 4254       /lib/arm-linux-gnueabihf/libc-2.13.so
b6ea9000-b6eac000 rw-p 00000000 00:00 0 
b6eac000-b6ec0000 r-xp 00000000 b3:02 4247       /lib/arm-linux-gnueabihf/libpthread-2.13.so
b6ec0000-b6ec7000 ---p 00014000 b3:02 4247       /lib/arm-linux-gnueabihf/libpthread-2.13.so
b6ec7000-b6ec8000 r--p 00013000 b3:02 4247       /lib/arm-linux-gnueabihf/libpthread-2.13.so
b6ec8000-b6ec9000 rw-p 00014000 b3:02 4247       /lib/arm-linux-gnueabihf/libpthread-2.13.so
b6ec9000-b6ecb000 rw-p 00000000 00:00 0 
b6ecb000-b6ee0000 r-xp 00000000 b3:02 44311      /usr/lib/arm-linux-gnueabihf/libbluetooth.so.3.12.0
b6ee0000-b6ee7000 ---p 00015000 b3:02 44311      /usr/lib/arm-linux-gnueabihf/libbluetooth.so.3.12.0
b6ee7000-b6ee8000 r--p 00014000 b3:02 44311      /usr/lib/arm-linux-gnueabihf/libbluetooth.so.3.12.0
b6ee8000-b6eea000 rw-p 00015000 b3:02 44311      /usr/lib/arm-linux-gnueabihf/libbluetooth.so.3.12.0
b6ef8000-b6efa000 r-xp 00000000 b3:02 25761      /usr/lib/arm-linux-gnueabihf/libcofi_rpi.so
b6efa000-b6f01000 ---p 00002000 b3:02 25761      /usr/lib/arm-linux-gnueabihf/libcofi_rpi.so
b6f01000-b6f02000 rw-p 00001000 b3:02 25761      /usr/lib/arm-linux-gnueabihf/libcofi_rpi.so
b6f02000-b6f04000 r-xp 00000000 b3:02 4246       /lib/arm-linux-gnueabihf/libSegFault.so
b6f04000-b6f0b000 ---p 00002000 b3:02 4246       /lib/arm-linux-gnueabihf/libSegFault.so
b6f0b000-b6f0c000 r--p 00001000 b3:02 4246       /lib/arm-linux-gnueabihf/libSegFault.so
b6f0c000-b6f0d000 rw-p 00002000 b3:02 4246       /lib/arm-linux-gnueabihf/libSegFault.so
b6f0d000-b6f2a000 r-xp 00000000 b3:02 4248       /lib/arm-linux-gnueabihf/ld-2.13.so
b6f2e000-b6f32000 rw-p 00000000 00:00 0 
b6f32000-b6f33000 r--p 0001d000 b3:02 4248       /lib/arm-linux-gnueabihf/ld-2.13.so
b6f33000-b6f34000 rw-p 0001e000 b3:02 4248       /lib/arm-linux-gnueabihf/ld-2.13.so
bebd3000-bebf4000 rw-p 00000000 00:00 0 
bee7f000-bee80000 r-xp 00000000 00:00 0          [sigpage]
ffff0000-ffff1000 r-xp 00000000 00:00 0          [vectors]
Segmentation fault

Удаление /usr/lib/arm-linux-gnueabihf/libcofi_rpi.so из /etc/ld.so.preload дает мне тот же результат, за исключением того, что нет строк, содержащих libcofi_rpi.so.

Попытка создать статически связанный двоичный файл с -tags netgo -a -ldflags "-linkmode external -extldflags -static" дает мне «Illegal instruction» вместо «Segmentation fault».

Попытка собрать двоичный файл на самом Pi работает, однако я хочу выполнить кросс-компиляцию. И кросс-компиляция действительно работает, но только на ODROID-C1/Arch, а не на Raspberry Pi/Raspbian.

Точные шаги сборки, которые я использую, можно воспроизвести с помощью Docker:

$ docker run -it golang:1.4.1-cross bash

Внутри докера я запускаю:

echo "deb http://emdebian.org/tools/debian/ jessie main" >/etc/apt/sources.list.d/crosstools.list
curl -s http://emdebian.org/tools/debian/emdebian-toolchain-archive.key | apt-key add -
dpkg --add-architecture armhf
apt-get update
apt-get install -y crossbuild-essential-armhf libbluetooth-dev:armhf
export CC=arm-linux-gnueabihf-gcc
export CGO_ENABLED=1
export GOARCH=arm
export GOARM=6
go build -o test test.go

Это дает мне исполняемый файл с именем «test», который, как отмечалось выше, не будет работать на Pi.

Вот некоторая информация о моих тестовых устройствах:

Малина Пи Б+:

$ uname -a
Linux raspberrypi 3.18.5+ #744 PREEMPT Fri Jan 30 18:19:07 GMT 2015 armv6l GNU/Linux

$ cat /proc/cpuinfo
processor       : 0
model name      : ARMv6-compatible processor rev 7 (v6l)
BogoMIPS        : 2.00
Features        : half thumb fastmult vfp edsp java tls 
CPU implementer : 0x41
CPU architecture: 7
CPU variant     : 0x0
CPU part        : 0xb76
CPU revision    : 7
Hardware        : BCM2708
Revision        : 0010
Serial          : 000000002a69d702

$ ldd test
        /usr/lib/arm-linux-gnueabihf/libcofi_rpi.so (0xb6f01000)
        libbluetooth.so.3 => /usr/lib/arm-linux-gnueabihf/libbluetooth.so.3 (0xb6ed4000)
        libpthread.so.0 => /lib/arm-linux-gnueabihf/libpthread.so.0 (0xb6eb5000)
        libc.so.6 => /lib/arm-linux-gnueabihf/libc.so.6 (0xb6d84000)
        /lib/ld-linux-armhf.so.3 (0xb6f0e000) 

Установленные библиотеки Bluetooth:

$ dpkg -s libbluetooth3

Package: libbluetooth3
Status: install ok installed
Priority: optional
Section: libs
Installed-Size: 172
Maintainer: Debian Bluetooth Maintainers <[email protected]>
Architecture: armhf
Multi-Arch: same
Source: bluez
Version: 4.99-2
Replaces: libsdp2 (<= 1.5-2)
Depends: libc6 (>= 2.13-28)
Pre-Depends: multiarch-support
Conflicts: libsdp2 (<= 1.5-2)
Description: Library to use the BlueZ Linux Bluetooth stack
 BlueZ is the official Linux Bluetooth protocol stack. It is an Open Source
 project distributed under GNU General Public License (GPL).
Homepage: http://www.bluez.org

ОДРОИД-C1:

$ uname -a
Linux alarm 3.10.66-1-ARCH #1 SMP PREEMPT Wed Jan 28 18:12:35 MST 2015 armv7l GNU/Linux

$ cat /proc/cpuinfo
Processor       : ARMv7 Processor rev 1 (v7l)
processor       : 0
BogoMIPS        : 3.27

processor       : 1
BogoMIPS        : 3.27

processor       : 2
BogoMIPS        : 3.27

processor       : 3
BogoMIPS        : 3.27

Features        : swp half thumb fastmult vfp edsp neon vfpv3 tls vfpv4 
CPU implementer : 0x41
CPU architecture: 7
CPU variant     : 0x0
CPU part        : 0xc05
CPU revision    : 1

Hardware        : ODROIDC
Revision        : 000a
Serial          : 1b00000000000000

$ ldd test
       libbluetooth.so.3 => /usr/lib/libbluetooth.so.3 (0xb6eaf000)
       libpthread.so.0 => /usr/lib/libpthread.so.0 (0xb6e87000)
       libc.so.6 => /usr/lib/libc.so.6 (0xb6d48000)
       /lib/ld-linux-armhf.so.3 (0xb6ed1000)

Установленные библиотеки Bluetooth и файлы заголовков разработки:

$ pacman -Qe bluez
bluez 5.27-1

Среда сборки докера

$ uname -a
Linux 094aa2ed34a5 3.18.5-gentoo-tp #1 SMP Fri Feb 6 20:14:55 CET 2015 x86_64 GNU/Linux

Установлены заголовки разработки Bluetooth:

$ dpkg -s libbluetooth-dev:armhf
Package: libbluetooth-dev
Status: install ok installed
Priority: extra
Section: libdevel
Installed-Size: 429
Maintainer: Debian Bluetooth Maintainers <[email protected]>
Architecture: armhf
Source: bluez (5.23-2)
Version: 5.23-2+b1
Replaces: libsdp2-dev (<= 1.5.2)
Provides: libbluetooth3-dev
Depends: libbluetooth3 (= 5.23-2+b1), libc6-dev | libc-dev
Suggests: pkg-config
Conflicts: bluez-pan, libbluetooth-dev, libsdp2-dev (<= 1.5.2)
Description: Development files for using the BlueZ Linux Bluetooth library
 BlueZ is the official Linux Bluetooth protocol stack. It is an Open Source
 project distributed under GNU General Public License (GPL).
Homepage: http://www.bluez.org

Установка той же версии libbluetooth-dev в контейнере Docker, что и на Pi, не имеет значения.


Копирование более нового libbluetooth.so из Джесси в Уизи дает мне эту ошибку:

./test: /lib/arm-linux-gnueabihf/libc.so.6: version `GLIBC_2.15' not found (required by /home/pi/libbluetooth.so.3.17.11)

ОБНОВИТЬ:

Пробовал с Arch на Pi, кросс-скомпилированный двоичный файл также дает ошибку сегментации, выдавая одно и то же сообщение ("Illegal instruction (core dumped)") с GOARM=5, 6 или 7.

Пока что я не нашел способа кросс-компилировать код CGO для Pi, связанный с libbluetooth.

Завтра попробую с Raspberry Pi 2.


person Attila O.    schedule 09.02.2015    source источник
comment
Вы пытаетесь скомпилировать в Raspberry Pi?   -  person yograterol    schedule 09.02.2015
comment
Попытка собрать двоичный файл на самом Pi работает, однако я хочу выполнить кросс-компиляцию.   -  person kwolfe    schedule 09.02.2015


Ответы (1)


Итак, позвольте мне ответить на мой собственный вопрос, сделав вывод после нескольких недель проб и ошибок, что…

… это просто не работает.

В крайнем случае я попытался взять тот же самый образ Raspbian, который использовал для компиляции приведенного выше кода, и запустить его с помощью . QEMU. И угадайте, что: я получаю segfault. Те же самые инструкции, использующие тот же образ, дают мне работающий исполняемый файл, когда я запускаю его на Pi, и segfault, когда я эмулирую Pi или пытаюсь кросс-компилировать его каким-либо образом.

В конце концов, это просто не стоит хлопот. Мы просто настроили выделенный Pi, который собирает наш проект, а «производственный» Pi просто загружает обновленный двоичный файл.

person Attila O.    schedule 04.03.2015
comment
Вы когда-нибудь заставляли это работать? В настоящее время я нахожусь в ситуации, когда кросс-компиляция значительно облегчит задачу, поскольку проект go, который я пытаюсь построить, слишком велик для оперативной памяти Pi, по-видимому. Я использую почти ту же цепочку инструментов и переменные среды, что и вы, и тоже получаю ошибки сегментации. Моим последним средством было бы увеличение размера подкачки на Pi, но я хотел бы избежать этого, если это возможно. Спасибо! - person Hadi Kocabas; 26.01.2016
comment
Нет, к сожалению, у меня не получилось. В конце концов я переключился на версии ARMv7, которые вроде бы работают. Я использовал ODROID-C, но Pi 2 тоже должен работать. Жаль, что мне все еще нужно скомпилировать на устройстве мой старый Pi B+. - person Attila O.; 26.01.2016
comment
Это облом. Думаю, я попытаюсь снова скомпилировать его на своем Pi B+ с увеличенным размером подкачки. Спасибо за ответ! - person Hadi Kocabas; 27.01.2016