Ich habe ein bisschen Probleme mit der Verwendung avrdude
vonBlitzmein Mikrocontroller.
Es hängt davon ablibm.so.6
GLIBC_2.29die es nicht finden kann. Es sucht dort, /usr/lib/libm.so.6
wo sich diese Datei tatsächlich befindet, ABER sie befindet sich auch in /lib/lib.so.6
.
Als ich also rannte
sudo pacman -S glibc
um die Bibliothek zu installieren/aktualisierenhttps://www.archlinux.org/packages/core/x86_64/glibc/
Ich bin sehr sicher, dass ich es nur installiert habe, um /lib/
…
Aber avrdude
ich suche weiter und /usr/lib
finde es immer noch nicht. Ich habe Schwierigkeiten, den Sinn dieser beiden Verzeichnisse zu verstehen, da sie die Dinge eher durcheinanderbringen als mir in meinem Fall helfen.
Wie mache ich es richtig?
BEARBEITEN
Ich wollte etwas Dummes tun, also habe ich es getan cp /lib/libm.so.6 /usr/lib/libm.o.6
, aber der cp
Befehl sagt mir, dass die Dateien gleich sind.
Jetzt verstehe ich nicht, warum ich avrdude
die richtige Version von GLIBC nicht finden kann, da diese (soweit ich das erkennen kann) ordnungsgemäß aktualisiert wird.
Antwort1
Bitte beachten Sie, dass die Installation
glibc
unvollständig ist.C runtime.
Zur VervollständigungC runtime
müssen Sie möglicherweise zusätzliche Header kopieren, die zum verwendeten Compiler passen, da die Verwendung von--sysroot
deren Suche auf beschränktsysroot
.
Es ist durchaus möglich, mehrere Versionen von glibc auf demselben System zu haben (das passiert uns jeden Tag).
Sie müssen jedoch wissen, dass glibc aus vielen Teilen besteht (mehr als 200 gemeinsam genutzte Bibliotheken), die alle übereinstimmen müssen. Einer dieser Teile ist ld-linux.so.2 und muss mit libc.so.6 übereinstimmen, sonst treten die angezeigten Fehler auf.
Der absolute Pfad zu ld-linux.so.2 wird beim Verknüpfen fest in die ausführbare Datei codiert und kann nach Abschluss des Verknüpfens nicht mehr einfach geändert werden.
Um eine ausführbare Datei zu erstellen, die mit der neuen glibc funktioniert, gehen Sie wie folgt vor:
g++ main.o -o myapp ... \
-Wl,--rpath=/path/to/newglibc \
-Wl,--dynamic-linker=/path/to/newglibc/ld-linux.so.2
Die -rpath
Linker-Option veranlasst den Runtime Loader, nach Bibliotheken zu suchen /path/to/newglibc
(so dass Sie sie vor dem Ausführen nicht festlegen müssen LD_LIBRARY_PATH
) und die -dynamic-linker
Option „backt“ den Pfad zur Korrektur ld-linux.so.2
in die Anwendung ein.
Wenn Sie die Anwendung nicht erneut verknüpfen können myapp
(z. B. weil es sich um eine Binärdatei eines Drittanbieters handelt), ist nicht alles verloren, aber es wird schwieriger. Eine Lösung besteht darin, eine geeignete chroot
Umgebung dafür einzurichten. Eine andere Möglichkeit ist die Verwendung vonAbonnierenund einBinäreditor.
LÖSUNG #1
LD_PRELOAD='mylibc.so anotherlib.so' program
Lösung Nr. 2
Kompilieren Sie Ihre eigene glibc ohne dedizierten GCC und verwenden Sie sie
Dieses Setup funktioniert möglicherweise und ist schnell, da es nicht die gesamte GCC-Toolchain neu kompiliert, sondern nur glibc.
Es ist jedoch nicht zuverlässig, da es Host-C-Laufzeitobjekte wie verwendet crt1.o,
crti.o
und crtn.o
von glibc bereitgestellt wird. Dies wird erwähnt unter:https://sourceware.org/glibc/wiki/Testing/Builds?action=recall&rev=21#Compile_against_glibc_in_an_installed_locationDiese Objekte führen die frühe Einrichtung durch, auf die glibc angewiesen ist, daher würde es mich nicht überraschen, wenn Dinge auf wundervolle und unglaublich subtile Weise abstürzen würden.
Eine zuverlässigere Einrichtung finden Sie weiter unten unter Einrichtung 2.
Lokal erstellen glibc
und installieren:
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`
Setup 1: Überprüfen des Builds
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);
}
Kompilieren und ausführen mit 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
Das Programm gibt die erwartete Ausgabe aus:
gnu_get_libc_version() = 2.28
The atomic counter is 10000
The non-atomic counter is 8674
Befehl adaptiert vonhttps://sourceware.org/glibc/wiki/Testing/Builds?action=recall&rev=21#Compile_against_glibc_in_an_installed_locationaber --sysroot ließ es mit folgendem fehlschlagen:
cannot find /home/ciro/glibc/build/install/lib/libc.so.6 inside /home/ciro/glibc/build/install
also habe ich es entfernt.
Die ldd-Ausgabe bestätigt, dass das gerade erstellte ldd und die Bibliotheken tatsächlich wie erwartet verwendet werden:
+ 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)
Die Debug-Ausgabe der GCC-Kompilierung zeigt, dass meine Host-Laufzeitobjekte verwendet wurden, was, wie bereits erwähnt, schlecht ist, aber ich weiß nicht, wie ich das umgehen kann. Sie enthält beispielsweise:
COLLECT_GCC_OPTIONS=/usr/lib/gcc/x86_64-linux-gnu/7/../../../x86_64-linux-gnu/crt1.o
Setup 1: glibc ändern
Lassen Sie uns nun glibc wie folgt ändern:
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)");
Dann kompilieren und installieren Sie glibc neu und kompilieren und führen Sie unser Programm erneut aus:
cd glibc/build
make -j `nproc`
make -j `nproc` install
./test_glibc.sh
und wir sehen, dass „gehackt“ wie erwartet ein paar Mal gedruckt wird.
Dies bestätigt weiter, dass wir tatsächlich die von uns kompilierte glibc verwendet haben und nicht die des Hosts.
Getestet auf Ubuntu 18.04.
Quellen:
https://stackoverflow.com/questions/847179/multiple-glibc-libraries-on-a-single-host/851229#851229