Kérdés:
Hogyan működik az API hívás Androidon (NDK)?
KYHSGeekCode
2018-12-09 20:36:02 UTC
view on stackexchange narkive permalink

A Windows platformon egy alkalmazás általában hivatkozik az IAT-ra (Access Access Table), hogy megkapja a kívánt API-k címét, majd felhívja. Ezután néhány mechanizmus megtörténik, ahogyan itt jól bemutatjuk.

Azonban nem tudom megtudni, hogyan működnek az API-hívások az Android NDK-n. Azt hiszem, az ELF fájlban nincs IAT. Meg tudná valaki mondani, hogy az API hogyan hívja az androidot, összeszerelési szinten?

Pl.

Amikor felhívom az ALooper_acquire (&mylooper) -ot, akkor összeáll mint

  mov r4, 0x2000; bl 0x7777fff0 mylooper címe; ALooper_acauire címe ... az ALooper_acquire ()  

után, majd a 0x7777fff0:

  Blah blah történetesen felhívja a rendszer api, ...  
Egy válasz:
Lero
2018-12-12 11:20:03 UTC
view on stackexchange narkive permalink

A kérdés megválaszolásához először tegyünk szilárd alapot az entitások és a definíciók tekintetében.

ELF az "Futtatható és összekapcsolható formátum" rövidítése.
Vagyis meghatározza a fájlok két típusának felépítését és alakját:

  • Futtatható fájlok (Megosztott objektumok * .so és önálló futtatható fájlok)
  • Linkelhetők (Objektumfájlok * .o)

Koncentráljunk a futtatható fájlokra.

A futtatható fájlok függőségeinek feloldása

Többek között ELF meghatározza a futtatható függőségek leírásának és megoldásának módszerét.

Függőségek

Egyszerűbben fogalmazva, a függőségek szükségesek külső szimbólumok. A szimbólumokat megnevezik (azonosítják) a memória darabjainak. Néhány darab adatdarab (globális változó), míg mások kódadat-darab (globális függvény). Mivel a szimbólum egy modul (más néven Shared Object) része, minden szükséges szimbólum párosul egy modullal.

Összefoglalva, a függőségekhez szükség van szimbólumokra és modulokra.

Ne feledje, hogy az OS API részét képező függvény lehet és általában külső szimbólum. Ez azonban nem mindig így van.

Függőségek leírása

Az ELF meghatározza a dinamikus szegmens nevű struktúrát, amelyet a betöltő számára szükséges információk tárolására használnak. (más néven dinamikus linker) egy futtatható fájl betöltési folyamatában. A futtatható függőségek leírása a dinamikus szegmensben van tárolva.

A szükséges szimbólumok a dinamikus szegmens által hivatkozott, dinamikus szimbólumtáblának nevezett táblába vannak rendezve:

] Hivatkozás egy szimbólumtáblázatra a Betöltött irányelvek alatt - https://elfy.io/KYze4

A dinamikus szimbólumtábla a szimbólumleírók összefüggő tömbje:

enter image description here .dynsym a Symbols alatt - https: // elfy .io / KYze4

A szükséges modulokat viszont közvetlenül a DT_NEEDED bejegyzésekkel írják le:

enter image description here Szükséges modulok a Loader irányelvek alapján - https://elfy.io/KYze4

Dinamikus link

Most készen állunk megvitatni azt a bekötési mechanizmust, amely lehetővé teszi egy futtatható fájl elérését függőségeihez amint a betöltő megoldja őket. Ezt egy külső függvényhívás lépéseinek követésével fogjuk megtenni.

Vegyünk példaként egy hívást az __android_log_print re (ARM 32 bit).

  ... 1d21a: f7fa e8e8 blx 173ec; __android_log_print @ plt ...  

A fenti egy olyan összeállítás, amely felhívja a __android_log_print fájlt, amely kinyomtatja a szöveget az Android Logcat programba. De valójában az a blx utasítás egy meghatározott kódcsonk egy speciális területen, az úgynevezett Eljárás linktábla (PLT) néven. A PLT-ben van egy kódcsonk minden szükséges külső funkcióhoz.

A __android_log_print csonkja: [ip, # 2548]! 000173f8 sleep @ plt: 173f8: e28fc600 add ip, pc, # 0, 12 173fc: e28cca11 add ip, ip, # 69632 17400: e5bcf9ec ldr pc, [ip, # 2540]! ...

A csonkban szereplő három utasítás a következőket teszi: (álkód)

  JUMP * (GOT_ADDRESS + GOT_OFFSET_OF (__ android_log_print)) 

A A Global Offset Table (GOT) egy mutatótábla. A GOT-ban minden külső funkcióhoz tartozik egy cella. Vagyis minden külső függvénynek megvan a saját cellája a GOT-ban. Miután a betöltési folyamat befejeződött , az X függvény cellája tartalmazza az X függvény memória címét.

  • A GOT jobb cellájának címszámítása 3-ra van felosztva a kódolási korlátozások miatt. pl .: A nagy eltolások nem kódolhatók egyetlen utasításba.

Az operációs rendszer betöltőjének feladata a GOT inicializálása a megfelelő memória címekkel, a korábban tárgyalt információk alapján.

A PLT és a GOT az ELF specifikáció részei.

Nagyon szépen köszönöm!! Úgy hangzik, hogy ez minden linux futtatható fájlra vonatkozik, igaz?
@KYHSGeekCode Még nem láttam olyan Linux futtatható fájlt, amely az ELF-től eltérő formátumban lett formázva. Tehát nyugodtan feltételezhetjük, hogy a Linux futtatható fájl ELF fájl lenne, és ebben az esetben igen, a mechanizmus ugyanaz lenne.
Az ELF nem a Linux kezdeti dinamikus futtatható formátuma volt. Néhány statikus bináris formátumot használnak ma. De ami igazán figyelemre méltó az Androidban, az az, hogy egyedi libc-t használ. Néhány beágyazott rendszer alternatív libc-ket is használ.


Ezt a kérdést és választ automatikusan lefordították angol nyelvről.Az eredeti tartalom elérhető a stackexchange oldalon, amelyet köszönünk az cc by-sa 4.0 licencért, amely alatt terjesztik.
Loading...