Egy assembly program hibája könnyen összetéveszthető egy környezeti hibával. Ha a shell nem találja az assemblert, a linker más architektúrájú objektumot kap, vagy a futtatási kísérlet rossz betöltőt használ, még nem a program algoritmusát kell javítanunk.
A mérnöki cél ezért egy kicsi, ellenőrizhető eszközlánc felépítése. A labor végén külön bizonyítékunk lesz arra, hogy:
Az előfeltétel a C fordítási láncolat és hova kerül az assembly fogalmainak ismerete. Most nem ismételjük meg a fordítási lépéseket: működő laborba helyezzük őket.
Laborprofil: Ubuntu Server 24.04 LTS, x86_64
fejlesztői gép; AArch64 célarchitektúra, A64 ISA, ARMv8-A alapprofil,
little-endian bájtsorrend; futtatás qemu-aarch64 user-mode
emulációval. Az alábbi kódokat itt nem futtattuk: minden megadott
eredmény várt ellenőrzési feltétel.
A fejlesztői gép (host) az a rendszer, amelyen a szerkesztő, a fordító és a többi fejlesztőeszköz fut. A célarchitektúra (target architecture) az az utasításkészlet és kapcsolódó környezet, amelyhez a kész programot előállítjuk.
Keresztfejlesztésről (cross-development) beszélünk, amikor a fejlesztőeszköz más célrendszerhez készít programot, mint amelyen maga fut. Ebben a laborban a fordító x86_64 Linux-program, de AArch64 Linux-programot állít elő.
| Szerep | A laborban | Ellenőrzés |
|---|---|---|
| Host kernelarchitektúrája | x86_64 | uname -m |
| Host Ubuntu-csomagarchitektúrája | amd64 |
dpkg --print-architecture |
| GCC célkonfigurációja | aarch64-linux-gnu |
aarch64-linux-gnu-gcc -dumpmachine |
| Elkészült program géptípusa | AArch64 | ELF-fejléc vizsgálata |
| Végrehajtási környezet | QEMU Linux user-mode | qemu-aarch64 |
Az amd64 és az x86_64 itt ugyanannak a
hostarchitektúrának eltérő elnevezése. Az arm64 ezzel
szemben az AArch64 gyakori disztribúciós neve; nem szabad összekeverni
az amd64 névvel.
Az aarch64-linux-gnu- előtag a célkonfigurációt
jelöli:
aarch64: célarchitektúra;linux: cél operációs rendszer;gnu: GNU-alapú felhasználói környezethez tartozó
toolchain-konfiguráció.Az előtag után következik az eszköz szerepe: gcc,
as, ld, objdump vagy
readelf. Az előtag nélküli gcc,
as és ld ezen a hoston rendszerint x86_64
célra dolgozik.
Két fontos kivétel van. A gdb-multiarch több
architektúrát támogató debugger, ezért nem ilyen előtaggal nevezzük meg.
A qemu-aarch64 pedig emulátor, nem fordítóeszköz.
A felhasználói módú emuláció (user-mode emulation) egy másik architektúrára készült felhasználói program végrehajtását teszi lehetővé. A QEMU feldolgozza az AArch64 utasításokat, és a támogatott Linux-rendszerhívásokat a host környezetéhez közvetíti.
Ebben az üzemmódban:
A QEMU tehát kiváló funkcionális labor: ellenőrizhető vele például egy számítás eredménye vagy egy program kilépési állapota. Az emuláció alatt mért futási időből viszont nem vezethető le közvetlenül egy fizikai ARM processzor ciklusszáma, utasításkésleltetése vagy áteresztőképessége.
A későbbi Cortex-M labor qemu-system-arm programot
használ majd. Ez külön futási modell, nem a mostani parancs másik
célarchitektúra-neve, és külön eszközlánc (arm-none-eabi-)
tartozik hozzá. Telepítését és ellenőrzését lent, a II. rész
eszközláncáról szóló szakasz írja le.
Először a hostot azonosítsuk, ne a telepített fordító nevéből következtessünk rá.
# Futtatás: Ubuntu host; tervezett cél: AArch64, qemu-user.
uname -m
dpkg --print-architecture
(
. /etc/os-release
printf '%s %s\n' "$ID" "$VERSION_ID"
)A baseline szerinti várt eredmények rendre: x86_64,
amd64, illetve ubuntu 24.04. A parancsok
sikeres kilépési állapota 0. Ha más rendszer jelenik meg, a
környezet eltér a könyv referenciaprofiljától; ez nem feltétlenül hiba,
de dokumentálandó eltérés.
Telepítsük a négy szükséges csomagot:
# Futtatás: Ubuntu 24.04 x86_64 host.
# Telepített eszközök célja: AArch64 Linux, qemu-user labor.
sudo apt-get update
sudo apt-get install \
gcc-aarch64-linux-gnu \
binutils-aarch64-linux-gnu \
gdb-multiarch \
qemu-userMindkét művelet várt kilépési állapota 0; az
update esetleges figyelmeztetéseit is ellenőrizni kell. A
telepítés rendszergazdai jogosultságot igényel, a későbbi fordítás és
emulált futtatás nem.
| Csomag | Feladat |
|---|---|
gcc-aarch64-linux-gnu |
C-fordító és fordításvezérlő AArch64 Linux-célhoz |
binutils-aarch64-linux-gnu |
Assembler, linker, objektum- és ELF-vizsgáló eszközök |
gdb-multiarch |
Több célarchitektúrát kezelő GDB |
qemu-user |
Felhasználói módú emulátorok, köztük qemu-aarch64 |
Az APT a szükséges függőségeket is telepíti. Ha nem talál egy
csomagot, előbb a csomaglisták frissítését, a disztribúció kiadását és a
hivatalos tárolókomponensek elérhetőségét vizsgáljuk. Egyes csomagokhoz
a universe komponensre is szükség lehet; a helyi
tárolókonfiguráció ellenőrzendő.
A „reprodukálható baseline” nem jelent automatikusan változatlan csomagverziókat. A 24.04 LTS frissítéseket kap, ezért a laborjegyzőkönyvben a tényleges verziókat is rögzíteni kell. Bitazonos környezethez ezen túl rögzített rendszerképre vagy csomagforrás-állapotra lenne szükség.
Laborkönyvtárak rendje. A könyv laborfájljainak
nevei szándékosan rövidek, és ismétlődnek: lab-main.c,
lab-Makefile, lab-exit.s vagy
lab-bits több alfejezetben is előfordul, eltérő
tartalommal. Közös munkakönyvtárban ezek felülírnák egymást. Ezért
minden alfejezet saját könyvtárban dolgozik, a könyv két része pedig
külön ágon:
~/arm-labor/
├── a64/ I. rész: AArch64 Linux; aarch64-linux-gnu-*, qemu-aarch64
│ ├── a000/
│ ├── a006/
│ ├── ...
│ └── zaro1/ az I. záróprojekt (a057–a060) közös könyvtára
└── cm/ II. rész: Cortex-M bare-metal; arm-none-eabi-*, qemu-system-arm
├── a006/ a Cortex-M eszközlánc smoke tesztje (lásd lent)
├── a061/
├── ...
└── zaro2/ a II. záróprojekt (a078–a081) közös könyvtára
A szabályok:
cp paranccsal másolja át. A
korábbi alfejezet könyvtárában nem dolgozunk tovább.a64/ és a cm/ ág nem keveredik: az
egyikben aarch64-linux-gnu- (Raspberry Pi-n natív)
eszközök, a másikban arm-none-eabi- eszközök futnak. Mivel
a könyvtárak függetlenek, két labor — akár a két profilból egyszerre —
párhuzamosan is felépíthető.Ennek az alfejezetnek az AArch64-próbái a
~/arm-labor/a64/a006/ könyvtárban készülnek:
# Futtatás: Ubuntu host; cél: AArch64 qemu-user labor.
mkdir -p ~/arm-labor/a64/a006
cd ~/arm-labor/a64/a006Siker esetén mindkét parancs állapota 0. A további
fájlokat ebben a könyvtárban készítjük.
# Futtatás: Ubuntu host; vizsgált cél: AArch64 Linux/qemu-user.
for tool in \
aarch64-linux-gnu-gcc \
aarch64-linux-gnu-as \
aarch64-linux-gnu-ld \
aarch64-linux-gnu-readelf \
aarch64-linux-gnu-objdump \
gdb-multiarch \
qemu-aarch64
do
command -v "$tool"
"$tool" --version
done
aarch64-linux-gnu-gcc -dumpmachineA command -v megmutatja, melyik programot választja a
shell. Ubuntu-csomagból telepített eszközöknél rendszerint
/usr/bin/ alatti elérési utat várunk. A
--version kiírásnak minden eszköznél meg kell jelennie; a
-dumpmachine várt eredménye
aarch64-linux-gnu.
A ciklus utolsó kilépési állapota önmagában nem igazolja az összes korábbi ellenőrzés sikerét: minden eszköz eredményét nézzük meg.
Rögzítsük a csomagverziókat is:
# Futtatás: Ubuntu host; cél: a qemu-user labor környezetének rögzítése.
dpkg-query -W -f='${binary:Package}\t${Version}\t${Architecture}\n' \
gcc-aarch64-linux-gnu \
binutils-aarch64-linux-gnu \
gdb-multiarch \
qemu-user > lab-packages.txt
cat lab-packages.txtA várt eredmény négy csomagbejegyzés, konkrét verziószámokkal. A
GCC-csomag lehet verziózott fordítócsomagra mutató csomag, ezért a
csomaglista mellett a fordító saját --version kimenete is
fontos.
Ha a felsorolt csomagok architektúrája amd64, az nem
cáfolja az AArch64 célt: maguk az eszközök a hoston futnak.
A teszt két részből áll. Először lefordítunk egy C-függvényt objektumfájllá. Ezután egy önálló assembly programmal külön ellenőrizzük az assembler–linker–emulátor láncot. A C-objektumot szándékosan nem linkeljük a második programba: így könnyebb elkülöníteni a hibaforrásokat.
Mentsük lab-compiler.c néven:
/* C-forrás; cél: AArch64 Linux, ARMv8-A, little-endian. */
unsigned lab_probe(void)
{
return 42u;
}Ez csak fordítási próba, ezért nem kell hozzá main és
futtatókörnyezet.
Mentsük lab-exit.s néven. A teljes példa A64 ISA
/ AArch64, I. rész kontextusú; a ponttal kezdődő sorok GNU
assembler-direktívák, nem processzorutasítások.
.section .text // GNU as/ELF direktíva, AArch64 cél
.global _start // GNU as/ELF direktíva, AArch64 cél
.type _start, %function // GNU as/ELF direktíva, AArch64 cél
_start:
movz w0, #42 // A64: W0 = 42, kilépési argumentum
movz w8, #93 // A64: W8 = 93, Linux exit hívásszáma
svc #0 // A64: Linux rendszerhívás kezdeményezése
.size _start, . - _start // GNU as/ELF direktíva, AArch64 cél
.section .note.GNU-stack,"",%progbits // GNU as/ELF: nem végrehajtható verem jelzéseA kód most tesztadapter; részletes tárgyalása az első assembly programnál és a Linux syscall-konvenciónál következik.
A szükséges értelmezés:
MOVZ itt 32 bites, előjel nélküli értékként
beállítja a W0, illetve W8 regisztert.MOVZ immediate mezője 16 bites, előjel nélküli
konstans. A 32 bites változat eltolása 0 vagy
16 bit lehet; itt az elhagyott eltolás 0.SVC szintén 16 bites, előjel nélküli immediate
mezőt fogad; itt az érték 0.93 nem az A64 ISA által kijelölt „kilépési utasítás”,
hanem az AArch64 Linux rendszerhívási felületének exit
hívásszáma.A program egyetlen szála 42 állapottal kilép. Nem
használ C-könyvtárat vagy dinamikus betöltőt.
# Host: Ubuntu 24.04 x86_64.
# Cél: AArch64/A64, ARMv8-A, little-endian; futtató: qemu-user.
aarch64-linux-gnu-gcc \
-std=c17 -Wall -Wextra -O2 -march=armv8-a -mlittle-endian \
-c lab-compiler.c -o lab-compiler.o &&
aarch64-linux-gnu-as \
-march=armv8-a -EL -o lab-exit.o lab-exit.s &&
aarch64-linux-gnu-ld \
-EL -e _start -o lab-exit lab-exit.o &&
aarch64-linux-gnu-readelf -h lab-compiler.o lab-exit &&
aarch64-linux-gnu-readelf -l lab-exitA && miatt egy hibás lépés után nem indul el a
következő. A fordítás, assemblálás és linkelés várt állapota
0.
Az ELF-vizsgálat ellenőrzési feltételei:
| Tulajdonság | lab-compiler.o |
lab-exit |
|---|---|---|
| Osztály | ELF64 | ELF64 |
| Géptípus | AArch64 | AArch64 |
| Bájtsorrend | little-endian | little-endian |
| Fájltípus | REL, relokálható objektum |
EXEC, végrehajtható fájl |
| Dinamikus betöltő | Nem releváns | Nincs INTERP programfejléc |
Az ELF64 önmagában nem elegendő: egy x86_64 objektum is lehet ELF64. A géptípust külön ellenőrizzük.
# Target: AArch64 Linux-program, qemu-user futtatással.
lab_status=0
qemu-aarch64 ./lab-exit || lab_status=$?
printf 'QEMU kilépési állapota: %s\n' "$lab_status"
test "$lab_status" -eq 42A vendégprogram nem ír szöveget. A shell várt kiírása:
QEMU kilépési állapota: 42. A záró test
sikeres állapota 0.
A 42 itt szándékos teszteredmény, nem váratlan hiba. A
feltételes állapotrögzítés olyan shellben is kezelni tudja, amely
egyébként megállna egy nem nulla állapotú parancsnál.
Végül ellenőrizzük a debugger célfelismerését:
# Debugger: Ubuntu x86_64 hoston; vizsgált fájl: AArch64 qemu-user cél.
gdb-multiarch -nx -batch \
-ex 'file lab-exit' \
-ex 'show architecture' \
-ex 'info files'Várt állapot: 0; a kimenetben AArch64 architektúra és a
betöltött fájl adatai jelennek meg. Ez fájlbetöltési próba, nem emulált
végrehajtás. A GDB run parancsa önmagában nem alakítja át
az x86_64 hostot AArch64 géppé; a QEMU-hoz kapcsolt hibakeresést később
építjük fel.
Az eddig telepített aarch64-linux-gnu- eszközlánc
nem a Cortex-M eszközlánca. AArch64 Linux-felhasználói
programot készít: A64 utasításokat és ELF64 fájlt,
Linux-rendszerhívásokkal és C-könyvtárral. A II. rész Cortex-M3
(Armv7-M) magon dolgozik, Thumb-2 utasításkészlettel, operációs rendszer
nélkül. Ehhez külön eszközlánc (arm-none-eabi-) és külön
emulátor (qemu-system-arm) kell. Az I. részhez ez a szakasz
nem szükséges, de legkésőbb a Thumb-2, a Cortex-M futási modell és a minimal
runtime fejezet előtt végre kell hajtani.
| I. rész | II. rész | |
|---|---|---|
| Célkonfiguráció | aarch64-linux-gnu |
arm-none-eabi |
| Utasításkészlet | A64 | Thumb-2 (T32), Armv7-M |
| ELF-osztály | ELF64 | ELF32 |
| Futtatás | qemu-aarch64 (user-mode) |
qemu-system-arm -machine mps2-an385 (system-mode) |
| Operációs rendszer | Linux, rendszerhívásokkal | nincs (bare-metal) |
| Munkakönyvtár-ág | ~/arm-labor/a64/ |
~/arm-labor/cm/ |
# Futtatás: Ubuntu 24.04 x86_64 host.
# Telepített eszközök célja: Cortex-M bare-metal, qemu-system labor.
sudo apt-get update
sudo apt-get install \
gcc-arm-none-eabi \
binutils-arm-none-eabi \
qemu-system-arm| Csomag | Feladat |
|---|---|
gcc-arm-none-eabi |
C-fordító bare-metal 32 bites Arm célhoz, köztük Cortex-M-hez |
binutils-arm-none-eabi |
Assembler, linker, objektum- és ELF-vizsgáló eszközök ugyanehhez a célhoz |
qemu-system-arm |
Teljes rendszeremulátor 32 bites Arm gépekhez, köztük az
mps2-an385 kártyához |
A debuggerhez nem kell új csomag: a már telepített
gdb-multiarch a Cortex-M célt is kezeli.
A Cortex-M próbák saját könyvtárban készülnek, az AArch64-próbáktól elkülönítve:
# Futtatás: Ubuntu host; cél: Cortex-M bare-metal labor.
mkdir -p ~/arm-labor/cm/a006
cd ~/arm-labor/cm/a006
for tool in \
arm-none-eabi-gcc \
arm-none-eabi-as \
arm-none-eabi-ld \
arm-none-eabi-readelf \
arm-none-eabi-objdump \
qemu-system-arm
do
command -v "$tool"
"$tool" --version
done
arm-none-eabi-gcc -dumpmachine
qemu-system-arm -machine help | grep mps2-an385
dpkg-query -W -f='${binary:Package}\t${Version}\t${Architecture}\n' \
gcc-arm-none-eabi \
binutils-arm-none-eabi \
qemu-system-arm > lab-packages.txt
cat lab-packages.txtVárt eredmény: minden eszköz kiírja a verzióját, a
-dumpmachine eredménye arm-none-eabi, a gépek
listájában szerepel az mps2-an385 sor, a
lab-packages.txt pedig három csomagbejegyzést
tartalmaz.
Mentsük lab-cm-probe.c néven:
/* C-forrás; cél: Cortex-M3, Armv7-M, Thumb-2, bare-metal. */
unsigned lab_probe(void)
{
return 42u;
}Először szándékosan a rossz fordítóval próbálkozunk:
# Várt eredmény: HIBA. Az AArch64 fordító nem ismeri a Thumb/M-profile célt.
aarch64-linux-gnu-gcc -mcpu=cortex-m3 -mthumb -c lab-cm-probe.c -o lab-wrong.o
echo "állapot: $?"A várt eredmény nem nulla állapot és hibaüzenet az ismeretlen
-mcpu értékről, illetve a -mthumb kapcsolóról;
a pontos szöveg GCC-verziófüggő. Ha ez a parancs sikerülne, az
aarch64-linux-gnu-gcc név valójában más fordítóra mutatna —
ezt command -v-vel ellenőrizni kell.
Mentsük lab-cm-smoke.s néven. A program egy kételemű
vektortáblából (kezdeti veremmutató és Reset-cím) és egy reset-kezelőből
áll, amely semihostinggal szöveget ír ki, majd leállítja a QEMU-t. A
részleteket a vektortábla és a startup kód alfejezetei tárgyalják; itt csak az
eszközláncot ellenőrizzük vele.
/* Cél: Cortex-M3 (Armv7-M), Thumb-2; futtató: qemu-system-arm mps2-an385. */
.syntax unified
.cpu cortex-m3
.thumb
.section .text
lab_vectors: @ vektortábla a 0x00000000 címen
.word 0x20004000 @ [0] kezdeti MSP: verem teteje az SRAM-ban
.word reset_handler @ [1] Reset; a .thumb_func miatt páratlan cím
.thumb_func
.global reset_handler
reset_handler:
movs r0, #0x04 @ semihosting SYS_WRITE0: nullvégű szöveg
ldr r1, =lab_msg
bkpt #0xab @ semihosting hívás
movs r0, #0x18 @ semihosting SYS_EXIT
ldr r1, =0x20026 @ ADP_Stopped_ApplicationExit: QEMU 0-val kilép
bkpt #0xab
1: b 1b @ ide nem jut el a vezérlés
.section .rodata
lab_msg:
.asciz "Cortex-M smoke: OK\n"Fordítás, assemblálás, linkelés és ELF-vizsgálat:
# Host: Ubuntu 24.04 x86_64.
# Cél: Cortex-M3, Armv7-M, Thumb-2, little-endian; futtató: qemu-system-arm.
arm-none-eabi-gcc \
-std=c17 -Wall -Wextra -O2 -mcpu=cortex-m3 -mthumb \
-c lab-cm-probe.c -o lab-cm-probe.o &&
arm-none-eabi-as \
-mcpu=cortex-m3 -mthumb -o lab-cm-smoke.o lab-cm-smoke.s &&
arm-none-eabi-ld \
-Ttext=0x00000000 -e reset_handler \
-o lab-cm-smoke.elf lab-cm-smoke.o &&
arm-none-eabi-readelf -h lab-cm-probe.o lab-cm-smoke.elf| Tulajdonság | lab-cm-probe.o |
lab-cm-smoke.elf |
|---|---|---|
| Osztály | ELF32 | ELF32 |
| Géptípus | ARM | ARM |
| Bájtsorrend | little-endian | little-endian |
| Fájltípus | REL |
EXEC |
| Flags | Version5 EABI |
Version5 EABI |
| Belépési pont | nem releváns | páratlan cím (0x9): Thumb-bit = 1 |
Futtatás:
# Target: Cortex-M3 bare-metal, qemu-system-arm, semihosting.
lab_status=0
timeout 10 qemu-system-arm -machine mps2-an385 -cpu cortex-m3 \
-nographic -semihosting \
-kernel lab-cm-smoke.elf || lab_status=$?
printf 'QEMU kilépési állapota: %s\n' "$lab_status"
test "$lab_status" -eq 0Várt kiírás: Cortex-M smoke: OK, majd
QEMU kilépési állapota: 0. A timeout védi a
labort a lefagyástól: a 124-es állapot azt jelenti, hogy a
QEMU 10 másodperc alatt sem állt le. Ilyenkor először a
-semihosting kapcsoló meglétét és a vektortábla
elhelyezését kell ellenőrizni
(arm-none-eabi-objdump -s -j .text lab-cm-smoke.elf: az
első két szó 0x20004000 és 0x00000009).
A labor akkor kész, ha mindkét profil tiszta állapotból felépül, és a két labor egymás zavarása nélkül, párhuzamosan is fut. Először töröljük a build-termékeket mindkét könyvtárból:
# Futtatás: Ubuntu host; mindkét profil build-termékeinek törlése.
rm -f ~/arm-labor/a64/a006/*.o ~/arm-labor/a64/a006/lab-exit
rm -f ~/arm-labor/cm/a006/*.o ~/arm-labor/cm/a006/lab-cm-smoke.elfEzután a saját könyvtárában ismételjük meg az AArch64 fordítási
blokkot (~/arm-labor/a64/a006) és a Cortex-M fordítási
blokkot (~/arm-labor/cm/a006). A két programot egy szkript
indítja egyszerre, és a két kilépési állapotot egyetlen
PASS/FAIL eredménnyé alakítja. Mentsük
~/arm-labor/lab-smoke-both.sh néven:
#!/bin/bash
# lab-smoke-both.sh — a két profil smoke tesztje párhuzamosan, közös PASS/FAIL eredménnyel.
# Futtatás: Ubuntu host, bash lab-smoke-both.sh; kilépési állapot: 0 = PASS, 1 = FAIL.
# Mindkét QEMU stdin-je /dev/null: a háttérfolyamat nem versenyez a terminálért.
( cd ~/arm-labor/a64/a006 && exec timeout 10 qemu-aarch64 ./lab-exit ) < /dev/null &
pid_a64=$!
( cd ~/arm-labor/cm/a006 &&
exec timeout 10 qemu-system-arm -machine mps2-an385 -cpu cortex-m3 \
-display none -monitor none -serial null -semihosting \
-kernel lab-cm-smoke.elf ) < /dev/null &
pid_cm=$!
wait "$pid_a64"; st_a64=$? # külön wait: mindkét állapot megmarad
wait "$pid_cm"; st_cm=$?
printf 'a64 állapot: %s (elvárt: 42)\n' "$st_a64"
printf 'cm állapot: %s (elvárt: 0)\n' "$st_cm"
if [ "$st_a64" -eq 42 ] && [ "$st_cm" -eq 0 ]; then
echo "SMOKE: PASS"
exit 0
fi
echo "SMOKE: FAIL"
exit 1A szkript három ponton tér el egy egyszerű
( … ) & wait mintától. (1) Mindkét
háttérfolyamat PID-jét elmenti, és külön
wait "$pid" kérdezi le az állapotukat. A paraméter nélküli
wait mindig 0-val tér vissza, egy záró echo
pedig a saját sikeres állapotával elfedné a futtatóét.
(2) Az exec miatt az alhéj állapota maga a
timeout, illetve a QEMU állapota; a timeout
124-et ad lefagyásnál, a hiányzó program 127-et, a sikertelen
cd nem nullát. (3) A semihostingos smoke
tesztnek nincs szüksége terminálra. A -nographic helyett
ezért -display none -monitor none -serial null áll, és
mindkét QEMU bemenete /dev/null, így a háttérbe tett
folyamat nem versenyez a terminálbemenetért. A semihosting-kimenet
(Cortex-M smoke: OK) chardev megadása nélkül a QEMU
szabványos hibakimenetére kerül, ezért továbbra is látszik.
cd ~/arm-labor
bash lab-smoke-both.sh; echo "kilépési állapot: $?"Várt eredmény (a Cortex-M smoke: OK sor helye a két
folyamat sorrendjétől függ):
Cortex-M smoke: OK
a64 állapot: 42 (elvárt: 42)
cm állapot: 0 (elvárt: 0)
SMOKE: PASS
kilépési állapot: 0
Minden más eset FAIL, és a szkript 1-gyel tér vissza: például ha a
lab-exit nem 42-vel lép ki, ha a QEMU hiányzik
(127), vagy ha a Cortex-M program nem áll le 10 másodpercen
belül (124). Ha az egyik profil csak akkor működik, ha a
másik nem fut, vagy ha egy fájlt a másik könyvtárból kellene átvenni, a
két labor nincs elkülönítve.
A hibakeresés sorrendje legyen: tünet → hipotézis → adatgyűjtés → egy változtatás → új ellenőrzés.
| Tünet | Lehetséges ok | Első ellenpróba |
|---|---|---|
command not found |
Hiányzó csomag vagy hibás PATH |
command -v, majd csomagvizsgálat |
| A csomag telepítve van, de a program nem található | A könyvtára nincs a PATH-ban |
Teljes elérési úttal indítás |
| A linker inkompatibilis objektumot jelez | Host- és céleszközök keveredtek | Objektumok Machine mezője |
Exec format error közvetlen indításkor |
A host nem kezeli közvetlenül az AArch64 fájlt | Explicit qemu-aarch64 |
| A QEMU hiányzó betöltőt említ | Dinamikusan linkelt célprogramhoz nincs megfelelő célkörnyezet | readelf -l, INTERP keresése |
arm-none-eabi-gcc: command not found |
A II. rész eszközlánca nincs telepítve; az
aarch64-linux-gnu- nem helyettesíti |
dpkg-query -W gcc-arm-none-eabi |
A qemu-system-arm nem áll le (timeout után
124) |
Hiányzó -semihosting, vagy a vektortábla nem a
0x00000000 címen van |
arm-none-eabi-objdump -s -j .text |
| Egy korábbi alfejezet példája hirtelen mást csinál | Közös munkakönyvtárban egy azonos nevű fájl felülíródott | pwd, a Munkakönyvtár blokk újraolvasása |
Például egy assembler-elérési hiba vizsgálata:
# Futtatás: Ubuntu host; vizsgált eszköz célja: AArch64.
command -v aarch64-linux-gnu-as
dpkg-query -W binutils-aarch64-linux-gnu
printf '%s\n' "$PATH"
/usr/bin/aarch64-linux-gnu-as --versionHa a csomagvizsgálat és a teljes útvonalas indítás sikeres, de a
command -v nem találja az eszközt, erős a
PATH-hiba hipotézise. Egyetlen parancsra korlátozott
ellenpróba:
# Futtatás: Ubuntu host; ideiglenes PATH, AArch64 assembler ellenőrzése.
PATH="/usr/bin:/bin:$PATH" aarch64-linux-gnu-as --versionVárt állapot: 0. Ez nem módosítja tartósan a shell
konfigurációját. A végleges javítás előtt keressük meg, hol veszett el a
megfelelő útvonal.
Közvetlen ./lab-exit indítás egyes gépeken automatikus
binárisformátum-kezelés miatt működhet. Ez nem bizonyít natív AArch64
végrehajtást. A reprodukálható labor mindig explicit
qemu-aarch64 parancsot használ.
(magyarázó, alapszint — cél:
megértés-ellenőrzés) A uname -m eredménye
x86_64, a GCC -dumpmachine eredménye
aarch64-linux-gnu, a csomagarchitektúra pedig
amd64. Miért nincs ellentmondás?
(implementációs, alapszint — cél: rutinépítés)
Módosítsd a lab-exit.s programot úgy, hogy 17
állapottal lépjen ki. Assembláld és linkeld újra, majd futtasd QEMU-val.
Melyik ellenőrző feltételt kell megváltoztatni?
(hibakeresési, középszint — cél: rutinépítés) A
binutils-aarch64-linux-gnu telepítve van. Az assembler
rövid névvel nem indul, teljes elérési úttal igen. Írd le az
adatgyűjtést, egyetlen ellenpróbát és a várt következtetést.
(verifikációs, középszint — cél: megértés-ellenőrzés) Egy társad szerint az ELF64 fejléc és a sikeres közvetlen futtatás elegendő az AArch64 labor igazolására. Adj két ellenérvet és két jobb ellenőrzést.
1. megoldás — Segítség. Gondold át, hogy az
amd64 és az aarch64-linux-gnu két különböző
dolgot neveznek meg: melyik a futtatott, és melyik az előállított kód
architektúrája?
1. megoldás — Teljes megoldás. A hoston x86_64
programok futnak; ezt az Ubuntu csomagkezelője amd64 néven
jelöli. A cross-GCC ilyen hostprogram, amely AArch64 célkódot készít. A
host és a cél eltérő szerepet nevez meg.
2. megoldás — Segítség. Az A64 MOVZ 16
bites immediate mezejébe nézd meg, belefér-e a 17; a shell
oldali ellenőrzés egyetlen számértékét kell követnie a
kódváltozásnak.
2. megoldás — Teljes megoldás. Az A64
movz w0, #42 helyére A64 movz w0, #17 kerül. A
17 belefér a 16 bites immediate mezőbe. Az assembler–linker
lépéssort újra kell futtatni; különben a régi binárist vizsgáljuk. A
shell feltétele test "$lab_status" -eq 17 lesz. A
Linux-hívásszámot tartalmazó A64 W8 regiszter beállítása
változatlan.
3. megoldás — Segítség. Három különálló adatforrás
(command -v, csomaginfo, PATH kiírása) közül
melyik mutatja meg, hogy a program telepítve van, de a shell nem találja
— és melyik egyváltozós ellenpróba dönti el ezt anélkül, hogy bármit
tartósan megváltoztatnánk?
3. megoldás — Teljes megoldás. A
command -v, a csomagvizsgálat és a PATH
kiírása együtt különíti el a hiányzó programot az elérési hibától. Az
ideiglenesen kiegészített PATH-tal megismételt indítás az
egyváltozós ellenpróba. Ha sikerül, nem indokolt első lépésként
újratelepíteni a csomagot.
4. megoldás — Segítség. Kérdezd meg, mit mond pontosan az ELF64 osztályjelző a géptípusról, és mi történhet, ha a host automatikus binárisformátum-kezelést végez — ezek külön-külön vezetnek a hiányosságokhoz és a jobb ellenőrzésekhez.
4. megoldás — Teljes megoldás. Az ELF64 csak a
fájlosztályt azonosítja, nem az utasításkészletet. A közvetlen futtatást
automatikusan közbeiktatott emulátor is lehetővé teheti. Jobb ellenőrzés
az ELF Machine: AArch64 mezője, valamint az explicit
QEMU-futtatás előre megadott kilépési állapottal.
Az Ubuntu 24.04 LTS hoston telepített cross-toolchain AArch64
Linux-programokat készít, miközben maga x86_64 környezetben fut. A labor
ellenőrzése több szintből áll: programelérhetőség, verziólekérdezés,
célkonfiguráció, ELF-fejléc, majd ismert eredményű végrehajtás. A QEMU
user-mode funkcionális tesztkörnyezet, nem teljes emulált gép és nem
hardverhű időmérő. A debugger fájlbetöltési próbája külön igazolja a
célarchitektúra felismerését. Hibánál előbb adatot gyűjtünk, majd
egyetlen tényezőt változtatunk. A rögzített csomagverziók teszik később
összehasonlíthatóvá a laborokat. A II. részhez külön eszközlánc
(arm-none-eabi-) és külön emulátor
(qemu-system-arm) tartozik, saját smoke teszttel; a két
profil a ~/arm-labor/a64/ és a ~/arm-labor/cm/
ágon, alfejezetenként külön könyvtárban dolgozik, ezért a laborok nem
írják felül egymás fájljait.
Az alábbiak dokumentációs kiindulópontok; ebben a munkafolyamatban nem megnyitott vagy ellenőrzött források.
A lab-smoke-both.sh állapotkezelését helyettesítő
qemu-* programokkal ellenőriztük: sikeres futásnál PASS és
0, hibás Cortex-M-állapotnál, lefagyásnál (124) és hiányzó
qemu-aarch64-nél (127) FAIL és 1. Valódi
QEMU-val, illetve azzal, hogy a semihosting-kimenet
-serial null mellett a szabványos hibakimenetre kerül,
ebben a munkafolyamatban nem futott; ez a hallgatói laborban
ellenőrizendő.
Ellenőrzési hiányok: a helyi Ubuntu-tárolók
állapota, a telepített csomagverziók és a parancsok tényleges eredménye
hallgatói ellenőrzést igényel. A current és
master dokumentáció eltérhet az Ubuntu 24.04 csomagolt
változataitól. A bemutatott kódhoz várt, nem ténylegesen mért vagy
futtatással igazolt eredményt adtunk. Ez a Cortex-M smoke tesztre is
vonatkozik: a gcc-arm-none-eabi,
binutils-arm-none-eabi és qemu-system-arm
csomagokkal a buildet és a futtatást ebben a munkafolyamatban nem
végeztük el, a readelf-táblázat és a vektortábla-szavak
levezetett értékek.