У меня есть некоторые трудности с avrdude
использованиемвспышкамой микроконтроллер.
Это зависит отlibm.so.6
ГЛИБК_2.29который он не может найти. Он ищет там /usr/lib/libm.so.6
, где этот файл на самом деле находится, НО он также находится в /lib/lib.so.6
.
Итак, пока я бежал,
sudo pacman -S glibc
для установки/обновления библиотекиhttps://www.archlinux.org/packages/core/x86_64/glibc/
Я совершенно уверен, что установил его только на /lib/
.
Но так как avrdude
он ищет /usr/lib
его, все равно не найдет. Мне трудно понять смысл этих двух каталогов, так как это скорее портит все, чем помогает в моем случае.
Как это сделать правильно?
РЕДАКТИРОВАТЬ
Я хотел сделать что-то глупое, поэтому я это сделал, cp /lib/libm.so.6 /usr/lib/libm.o.6
но cp
команда говорит мне, что файлы одинаковые.
Теперь я не понимаю, почему avrdude
не могу найти нужную версию GLIBC, ведь она обновлена должным образом (насколько я могу судить).
решение1
Обратите внимание, что установленный файл
glibc
неполный.C runtime.
Для завершенияC runtime
вам может потребоваться скопировать дополнительные заголовочные файлы, соответствующие используемому вами компилятору, поскольку использование--sysroot
ограничит их поиск файломsysroot
.
Вполне возможно, что в одной системе будет несколько версий glibc (мы делаем это каждый день).
Однако вам нужно знать, что glibc состоит из многих частей (более 200 общих библиотек), которые все должны совпадать. Одна из частей — ld-linux.so.2, и она должна соответствовать libc.so.6, иначе вы увидите ошибки, которые видите.
Абсолютный путь к ld-linux.so.2 жестко запрограммирован в исполняемом файле во время компоновки и не может быть легко изменен после завершения компоновки.
Чтобы создать исполняемый файл, который будет работать с новой библиотекой glibc, выполните следующие действия:
g++ main.o -o myapp ... \
-Wl,--rpath=/path/to/newglibc \
-Wl,--dynamic-linker=/path/to/newglibc/ld-linux.so.2
Параметр компоновщика -rpath
заставит загрузчик среды выполнения искать библиотеки /path/to/newglibc
(чтобы вам не пришлось устанавливать LD_LIBRARY_PATH
их перед запуском), а -dynamic-linker
параметр «запечет» путь для исправления ld-linux.so.2
в приложении.
Если вы не можете перелинковать myapp
приложение (например, потому что это сторонний двоичный файл), не все потеряно, но все становится сложнее. Одним из решений является настройка надлежащей chroot
среды для него. Другая возможность — использоватьртлдии адвоичный редактор.
РЕШЕНИЕ №1
LD_PRELOAD='mylibc.so anotherlib.so' program
Решение №2
скомпилируйте свой собственный glibc без выделенного GCC и используйте его
Такая настройка может работать и является быстрой, поскольку она не перекомпилирует всю цепочку инструментов GCC, а только glibc.
Но это не надежно, так как использует объекты среды выполнения хоста C, такие как crt1.o,
crti.o
, и crtn.o
предоставляемые glibc. Это упоминается в:https://sourceware.org/glibc/wiki/Testing/Builds?action=recall&rev=21#Compile_against_glibc_in_an_installed_locationЭти объекты выполняют раннюю настройку, на которую полагается glibc, поэтому я не удивлюсь, если что-то будет вылетать чудесным и удивительно незаметным образом.
Для более надежной настройки см. настройку 2 ниже.
Сборка glibc
и установка локально:
export glibc_install="$(pwd)/glibc/build/install"
git clone git://sourceware.org/git/glibc.git
cd glibc
git checkout glibc-2.28
mkdir build
cd build
../configure --prefix "$glibc_install"
make -j `nproc`
make install -j `nproc`
Настройка 1: проверка сборки
test_glibc.c
#define _GNU_SOURCE
#include <assert.h>
#include <gnu/libc-version.h>
#include <stdatomic.h>
#include <stdio.h>
#include <threads.h>
atomic_int acnt;
int cnt;
int f(void* thr_data) {
for(int n = 0; n < 1000; ++n) {
++cnt;
++acnt;
}
return 0;
}
int main(int argc, char **argv) {
/* Basic library version check. */
printf("gnu_get_libc_version() = %s\n", gnu_get_libc_version());
/* Exercise thrd_create from -pthread,
* which is not present in glibc 2.27 in Ubuntu 18.04.
* https://stackoverflow.com/questions/56810/how-do-i-start-threads-in-plain-c/52453291#52453291 */
thrd_t thr[10];
for(int n = 0; n < 10; ++n)
thrd_create(&thr[n], f, NULL);
for(int n = 0; n < 10; ++n)
thrd_join(thr[n], NULL);
printf("The atomic counter is %u\n", acnt);
printf("The non-atomic counter is %u\n", cnt);
}
Скомпилируйте и запустите с помощью test_glibc.sh
:
#!/usr/bin/env bash
set -eux
gcc \
-L "${glibc_install}/lib" \
-I "${glibc_install}/include" \
-Wl,--rpath="${glibc_install}/lib" \
-Wl,--dynamic-linker="${glibc_install}/lib/ld-linux-x86-64.so.2" \
-std=c11 \
-o test_glibc.out \
-v \
test_glibc.c \
-pthread \
;
ldd ./test_glibc.out
./test_glibc.out
Программа выводит ожидаемое:
gnu_get_libc_version() = 2.28
The atomic counter is 10000
The non-atomic counter is 8674
Команда адаптирована изhttps://sourceware.org/glibc/wiki/Testing/Builds?action=recall&rev=21#Compile_against_glibc_in_an_installed_locationно --sysroot вызвал сбой:
cannot find /home/ciro/glibc/build/install/lib/libc.so.6 inside /home/ciro/glibc/build/install
поэтому я его удалил.
Вывод ldd подтверждает, что ldd и библиотеки, которые мы только что создали, действительно используются так, как и ожидалось:
+ ldd test_glibc.out
linux-vdso.so.1 (0x00007ffe4bfd3000)
libpthread.so.0 => /home/ciro/glibc/build/install/lib/libpthread.so.0 (0x00007fc12ed92000)
libc.so.6 => /home/ciro/glibc/build/install/lib/libc.so.6 (0x00007fc12e9dc000)
/home/ciro/glibc/build/install/lib/ld-linux-x86-64.so.2 => /lib64/ld-linux-x86-64.so.2 (0x00007fc12f1b3000)
Отладочный вывод компиляции gcc показывает, что использовались мои объекты среды выполнения хоста, что, как упоминалось ранее, плохо, но я не знаю, как это обойти, например, он содержит:
COLLECT_GCC_OPTIONS=/usr/lib/gcc/x86_64-linux-gnu/7/../../../x86_64-linux-gnu/crt1.o
Настройка 1: изменение glibc
Теперь давайте изменим glibc следующим образом:
diff --git a/nptl/thrd_create.c b/nptl/thrd_create.c
index 113ba0d93e..b00f088abb 100644
--- a/nptl/thrd_create.c
+++ b/nptl/thrd_create.c
@@ -16,11 +16,14 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
+#include <stdio.h>
+
#include "thrd_priv.h"
int
thrd_create (thrd_t *thr, thrd_start_t func, void *arg)
{
+ puts("hacked");
_Static_assert (sizeof (thr) == sizeof (pthread_t),
"sizeof (thr) != sizeof (pthread_t)");
Затем перекомпилируйте и переустановите glibc, а затем перекомпилируйте и перезапустите нашу программу:
cd glibc/build
make -j `nproc`
make -j `nproc` install
./test_glibc.sh
и мы видим слово hacked напечатанным несколько раз, как и ожидалось.
Это еще раз подтверждает, что мы действительно использовали скомпилированную нами glibc, а не хостовую.
Протестировано на Ubuntu 18.04.
Источники:
https://stackoverflow.com/questions/847179/multiple-glibc-libraries-on-a-single-host/851229#851229