3.1 Labor-alapkörnyezet: eszközlánc telepítése és verifikáció

3.1.1 Miért kell külön ellenőrizni a labor környezetét?

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.

3.1.2 Fejlesztői gép, célarchitektúra és cross-toolchain

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:

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.

3.1.3 Mit biztosít a QEMU user-mode?

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.

3.1.4 Telepítés Ubuntu 24.04 LTS hoston

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-user

Mindké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.

3.1.5 Elérhetőség és verziók ellenőrzése

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:

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/a006

Siker 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 -dumpmachine

A 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.txt

A 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.

3.1.6 Kidolgozott példa: a teljes út ellenőrzése

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.

3.1.6.1 C-fordítási próba

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.

3.1.6.2 Önálló assembly futtatási próba

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ése

A 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:

A program egyetlen szála 42 állapottal kilép. Nem használ C-könyvtárat vagy dinamikus betöltőt.

3.1.6.3 Fordítás, assemblálás és linkelés

# 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-exit

A && 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.

3.1.6.4 Futtatás és debuggerpróba

# 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 42

A 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.

3.1.7 A II. rész eszközlánca: Cortex-M ellenőrzés és smoke teszt

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/

3.1.7.1 Telepítés és verziók

# 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.txt

Vá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.

3.1.7.2 Ellenpróba: az AArch64 eszközlánc nem helyettesíti

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.

3.1.7.3 Smoke teszt: Cortex-M3 program QEMU alatt

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 0

Vá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).

3.1.7.4 Elfogadás: tiszta környezet, két profil párhuzamosan

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.elf

Ezutá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 1

A 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.

3.1.8 Tipikus hibák és ellenpróbák

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 --version

Ha 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 --version

Vá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.

3.1.9 Feladatok

  1. (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?

  2. (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?

  3. (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.

  4. (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.

3.1.10 Megoldások

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.

3.1.11 Rövid összefoglaló

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.

3.1.12 Források és ellenőrzési hiányok

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.