LINUX.ORG.RU

Бинарник был открыт, но «No such file or dirrectory”

 , , , ,


1

1

Пытаюсь использовать функцию из libxxx.so, взятой из Windriver arm hf 2.6.32. Эмулирую на qemu Debian wheezy hf 3.2.0. Скомпилив простейший бинарник hello, где вызываю dlopen на libxxx.so, получаю ошибку «cannot open shared object file: No such file or dirrectory”. Хотя:

strace:

open("/usr/src/hello/libxxx.so", O_RDONLY) = 3
read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0(\0\1\0\0\0\330\26\0\0004\0\0\0"..., 512) = 512
lseek(3, 53056, SEEK_SET) = 53056
read(3, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 1400) = 1400
lseek(3, 37784, SEEK_SET) = 37784
read(3, "A0\0\0\0aeabi\0\1&\0\0\0\0057-A\0\6\n\7A\10\1\t\2\n\4\22"..., 49) = 49
close(3) = 0
writev(2, [{"./hello", 7}, {": ", 2}, {"error while loading shared libra"..., 36}, {": ", 2}, {"libxxx.so", 13}, {": ", 2}, {"cannot open shared object file", 30}, {": ", 2}, {"No such file or directory", 25}, {"\n", 1}], 10./hello: error while loading shared libraries: libxxx.so: cannot open shared object file: No such file or directory
) = 120
exit_group(127)

# file libxxx.so:
ELF 32-bit LSB shared object, ARM, version 1 (SYSV), dynamically linked, not stripped
# uname -a:
Linux debian-armhf 3.2.0-4-vexpress #1 SMP Debian 3.2.51-1 armv7l GNU/Linux
# file hello:
ELF 32-bit LSB executable, ARM, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.26
# ldd hello : libdl.so.2 => /lib/arm-linux-gnueabihf/libdl.so.2 (0x76ee9000) libxxx.so => not found libc.so.6 => /lib/arm-linux-gnueabihf/libc.so.6 (0x76e01000) /lib/ld-linux-armhf.so.3 
# ldconfig -p | grep libxxx.so : libxxx.so (libc6) => /lib/libxxx.so (it's not a link)
# ldd libxxx.so : not a dynamic executable

readelf говорит, что для libxxx.so NEEDED только libc. Секцию ARM.attributes смотрел, сверял с родными либами...

Проверь совпадает ли ABI. Возможно на железке у тебя хардверные числа с плавающей точкой, а собираешься ты с софтверными.

xpahos ★★★★★ ()
Ответ на: комментарий от i-rinat

Ничего не выдает. А разве интерпретатор не подхватывается из запускаемого бинарника hello и дальше уже подхватывает либы?

botcser ()
Ответ на: комментарий от xpahos

Проверял по родной библиотеке, которая успешно вызывается, через readelf: Version5 EABI одинаковое (это?), ELF заголовок вообще один в один кроме размера и входной точки.

botcser ()

Если что, то после close(3) и write(ошибку) есть попытки:

stat64("/lib", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
open("/usr/lib/tls/v7l/neon/vfp/libxxx.so", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/usr/lib/tls/v7l/neon/vfp", 0x7eed73f0) = -1 ENOENT (No such file or directory)
open("/usr/lib/tls/v7l/neon/libxxx.so", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/usr/lib/tls/v7l/neon", 0x7eed73f0) = -1 ENOENT (No such file or directory)
open("/usr/lib/tls/v7l/vfp/libxxx.so", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/usr/lib/tls/v7l/vfp", 0x7eed73f0) = -1 ENOENT (No such file or directory)
open("/usr/lib/tls/v7l/libxxx.so", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/usr/lib/tls/v7l", 0x7eed73f0)  = -1 ENOENT (No such file or directory)
open("/usr/lib/tls/neon/vfp/libxxx.so", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/usr/lib/tls/neon/vfp", 0x7eed73f0) = -1 ENOENT (No such file or directory)
open("/usr/lib/tls/neon/libxxx.so", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/usr/lib/tls/neon", 0x7eed73f0) = -1 ENOENT (No such file or directory)
open("/usr/lib/tls/vfp/libxxx.so", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/usr/lib/tls/vfp", 0x7eed73f0)  = -1 ENOENT (No such file or directory)
open("/usr/lib/tls/libxxx.so", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/usr/lib/tls", 0x7eed73f0)      = -1 ENOENT (No such file or directory)
open("/usr/lib/v7l/neon/vfp/libxxx.so", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/usr/lib/v7l/neon/vfp", 0x7eed73f0) = -1 ENOENT (No such file or directory)
open("/usr/lib/v7l/neon/libxxx.so", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/usr/lib/v7l/neon", 0x7eed73f0) = -1 ENOENT (No such file or directory)
open("/usr/lib/v7l/vfp/libxxx.so", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/usr/lib/v7l/vfp", 0x7eed73f0)  = -1 ENOENT (No such file or directory)
open("/usr/lib/v7l/libxxx.so", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/usr/lib/v7l", 0x7eed73f0)      = -1 ENOENT (No such file or directory)
open("/usr/lib/neon/vfp/libxxx.so", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/usr/lib/neon/vfp", 0x7eed73f0) = -1 ENOENT (No such file or directory)
open("/usr/lib/neon/libxxx.so", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/usr/lib/neon", 0x7eed73f0)     = -1 ENOENT (No such file or directory)
open("/usr/lib/vfp/libxxx.so", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/usr/lib/vfp", 0x7eed73f0)      = -1 ENOENT (No such file or directory)
open("/usr/lib/libxxx.so", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/usr/lib", {st_mode=S_IFDIR|0755, st_size=53248, ...}) = 0



Но при указании либы напрямую эти попытки становятся до успешного открытия libxxx.so.
botcser ()
Ответ на: комментарий от botcser

Ну как сказать...

lseek(3, 37784, SEEK_SET) = 37784
read(3, «A0\0\0\0aeabi\0\1&\0\0\0\0057-A\0\6\n\7A\10\1\t\2\n\4\22»..., 49) = 49

Очевидно ответ, в этих 49-ти байтах. Только их бы надо все показать.

unDEFER ★★★★ ()
Ответ на: комментарий от unDEFER

Я тоже так думал, смотрел, смотрел, сравнивал, сравнивал, вычитывал, вычитывал, но ничего полезного не выяснил) Вот libxxx.so:0x37784:

41 30 00 00 00 61 65 61 62 69 00 01 26 00 00 00
05 37 2D 41 00 06 0A 07 41 08 01 09 02 0A 04 12
04 14 01 15 01 17 03 18 01 19 01 1A 02 1B 03 22
01 00 00 00 00 00 00 00 2C 00 00 00 02 00 00 00 
00 00 04 00 00 00 00 00 D8

Вот libaudit.so (просто родная либа для сравнения):

41 34 00 00 00 61 65 61 62 69 00 01 2A 00 00 00 
05 37 2D 41 00 06 0A 07 41 08 01 09 02 0A 04 12
04 14 01 15 01 17 03 18 01 19 01 1A 02 1B 03 1C 
01 1E 02 2C 01 00 2E 73 68 73 74 72 74 61 62 00
2E 6E 6F 74 65 2E 67 6E 75 2E 62 75 69 6C 64 2D 
69 64 00

botcser ()
Ответ на: комментарий от xpahos

Вот libxxx.so:

ELF Header:
  Magic:   7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00 
  Class:                             ELF32
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              DYN (Shared object file)
  Machine:                           ARM
  Version:                           0x1
  Entry point address:               0x16d8
  Start of program headers:          52 (bytes into file)
  Start of section headers:          53056 (bytes into file)
  Flags:                             0x5000002, has entry point, Version5 EABI
  Size of this header:               52 (bytes)
  Size of program headers:           32 (bytes)
  Number of program headers:         5
  Size of section headers:           40 (bytes)
  Number of section headers:         35
  Section header string table index: 32

Вот libaudit.so (просто родная либа для сравнения):

ELF Header:
  Magic:   7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00 
  Class:                             ELF32
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              DYN (Shared object file)
  Machine:                           ARM
  Version:                           0x1
  Entry point address:               0x1f24
  Start of program headers:          52 (bytes into file)
  Start of section headers:          78368 (bytes into file)
  Flags:                             0x5000002, has entry point, Version5 EABI
  Size of this header:               52 (bytes)
  Size of program headers:           32 (bytes)
  Number of program headers:         6
  Size of section headers:           40 (bytes)
  Number of section headers:         26
  Section header string table index: 25

botcser ()
Ответ на: комментарий от botcser

Эх, кажется придётся долго изучать исходники dlopen до просветления... Но там настолько всё хитровывернуто.. Даже где он делает open не понятно, не то что read..

unDEFER ★★★★ ()
Ответ на: комментарий от botcser

Может быть там какие-то инструкции проскальзывают, которые процем не поддерживаются?

Бинарь бы ругался на них типа Illegal opcode, а вот если они в открываемой по dlopen либе, то может и подобная ошибка быть.

А без dlopen не пробовал? Я вижу, что либу ты явно прилинковал к file. Заголовочного файла у либы нет?

EXL ★★★★★ ()
Ответ на: комментарий от EXL

Заголовочного файла нет. Пробовал и явно и не явно линковать. Хотел без dlopen, но как? Гугл не помог. Вроде должен быть второй способ...

botcser ()
Ответ на: комментарий от botcser

А разве интерпретатор не подхватывается из запускаемого бинарника hello и дальше уже подхватывает либы?

Без понятия, никогда не вникал в детали.

i-rinat ★★★★★ ()
Ответ на: комментарий от botcser

Немного потыкал в исходники glibc, и нашёл там проверку секции .note.ABI-tag (а точнее, секций с PT_NOTE). Похоже, там указывается ожидаемая версия ядра, которая проверяется во время dlopen.

https://github.molgen.mpg.de/git-mirror/glibc/blob/20003c49884422da7ffbc459cd...

i-rinat ★★★★★ ()
Ответ на: комментарий от i-rinat

Вот это более похоже на истину. В дебиане готовых 2.6 образов squeeze arm под qemu нет, поэтому я взял 3.2 wheezy. Спасибо, проверю это - попробую даунгрейнуть или установить 2.6.

botcser ()
Ответ на: комментарий от botcser

Заголовочного файла нет.

Можно ведь создать. Либа сишная или приплюснутая? Реверсни либу, я раньше подобным занимался, вот даже мануал кину:

= Изучение разделяемых библиотек (so) =

Для того что бы выяснить какие функции экспортирует закрытая разделяемая библиотека (.so) и на основе этого написать свой C/C++ хидер (.h) воспользуемся двумя командами из пакета binutils. Поскольку формат ELF файлов не отличается для разных архитектур, то можно даже не устанавливать кросс утилиты.

Первая необходимая нам команда - "'readelf"' - позволяет получить самую разнообразную информацию о исполнимом файле или разделяемой библиотеки. Подробности можно узнать "man elf", нас же на данном этапе интересует только таблица символических имён (symbols) библиотеки. Извлечь её можно дав команду

{{{
readelf -s -W libyourlibrary.so
}}}

Здесь ключ "-s" указывает, что нам нужна именно таблица имён (symbols), а ключ "-W" заставляет не обрезать выводимые данные под ширину терминала.

Таблицу с именами мы получаем в следующем виде:

{{{
Num: Value Size Type Bind Vis Ndx Name
42: 42c11768 24 FUNC GLOBAL DEFAULT 10 _ZNK10CAM_Engine15isCameraRunningEv
43: 00000000 152 FUNC GLOBAL DEFAULT UND _ZN5QFileD1Ev
}}}

Имена у которых поле 'Value' равно нулю или поле 'Ndx' равно "'UND"' являются внешними по отношению к библиотеке, т.е. используются функциями библиотеки, но должны импортироватся из других библиотек. Их нам тоже необходимо будет отсечь.

Само имя функции переменной и т.п. содержится в последнем столбце. Имена используемые чистым "'C"' записываются как есть. Поскольку в "'C++"' существуют пространства имён, классы, перегрузка функции из имени в таблицы мы можем извлечь много полезной информации. В частности это список параметров.

Имена кодируются специальным образом (mangling) и имеют малочитаемый вид. Что бы расшифровать имя, воспользуемся командой "c++filt".

Что бы отсечь имена не экспортируемые библиотекой, отфильтруем вывод "readelf" с помощью скрипта "'awk"'. В итоге мы получаем цепочку команд:

{{{
readelf -s -W libezxcameraengine.so | awk '{ if($2) print $8 «\t\t // » $4 }' | c++filt | sort
}}}

На выходе мы получим отсортированный список всех функций и переменных в виде пригодном для копирования в заголовочный файл.

К сожалению, не существует простого способа узнать тип возвращаемого значения. Тут поможет анализ бинарного кода, но в большинстве случаев нужный тип можно угадать ;-)

И наконец для имён функций в формате чистого "'C"' необходимые параметры можно узнать только анализом бинарного кода.

---

Для обзора экспортируемых и используемых функций воспользуемся командой:

{{{
readelf -s -W libezxbluetooth.so | c++filt | sort -k 8
}}}

Список так же будет отсортирован по именам функций/переменных.

И наконец команда:

{{{
objdump -dR libezxbluetooth.so | c++filt
}}}

дизассемблирует бинарный код. Это конечно если у вас в системе установлен мультиархитектурный objdump. Иначе воспользуйтесь дампером из тулкита {{{/arm-eabi/bin/arm-linux-gnueabi-objdump}}}

Хотел без dlopen, но как?

Напрямую, как ты вызываешь функции из стандартной библиотеки.

EXL ★★★★★ ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.