Rosetta 2 Apple siliconilla varustetussa Macissa
Apple siliconilla varustettu Mac voi suorittaa x86_64-käskykannalle käännettyä koodia käyttäen Rosetta 2 ‑käännösmekanismia. Käännöstyyppejä on kaksi: ajonaikainen JIT (just-in-time) ja ennenaikainen AOT (ahead-of-time).
JIT-kääntäminen
JIT-kääntämistä käytettäessä x86_64-muotoinen Mach-O tunnistetaan aikaisessa kohdassa levytiedoston suorituspolussa. Kun tällaisia levytiedostoja tulee vastaan, kernel siirtää hallinnan erityiselle Rosetta-käännösosalle dynaamisten linkkien editorin (dyld(1)
) sijaan. Käännösosa kääntää sitten x86_64-sivut levytiedoston suorittamisen aikana. Tämä kääntäminen tapahtuu kokonaan prosessissa. Kernel vertaa edelleen kunkin x86_64-sivun kooditiivisteitä koodin allekirjoitukseen, joka on liitetty binääritiedostoon, kun sivu tuodaan sisään. Mikäli tiivisteet eivät täsmää, kernel pakottaa kyseiselle prosessille sopivan korjauskäytännön.
AOT-kääntäminen
Käytettäessä ennenaikaista (AOT) kääntämispolkua x86_64-binääritiedostot luetaan tallennustilasta aikoina, jotka järjestelmä määrittää optimaalisiksi koodin reaktionopeuden kannalta. Käännetyt artefaktit kirjoitetaan tallennustilaan erityistyyppisenä Mach-O-tiedostona. Tämä tiedosto on samankaltainen kuin suoritettava levytiedosto, mutta varustettu merkinnällä, joka kertoo sen olevan käännetty toisesta levytiedostosta.
Tässä mallissa AOT-käännetty artefakti saa kaikki identiteettitietonsa alkuperäiseltä suoritettavalta x86_64-levytiedostolta. Tämän sidoksen pakottamiseksi etuoikeutettu käyttäjätilan entiteetti allekirjoittaa käännösartefaktin käyttäen Secure Enclaven hallitsemaa laitekohtaista avainta. Avain vapautetaan vain etuoikeutetulle käyttäjätilan entiteetille, joka tunnistetaan sellaiseksi rajoitetulla oikeudella. Käännösartefaktia varten luotu koodihakemisto sisältää suoritettavan alkuperäisen x86_64-levytiedoston koodihakemiston tiivisteen. Itse käännösartefaktin allekirjoitusta kutsutaan lisäallekirjoitukseksi.
AOT-käännösputki alkaa samoin kuin JIT-käännösputki, eli kernel siirtää hallinnan ajonaikaiselle Rosettalle dynaamisten linkkien editorin (dyld(1)
) sijaan. Ajonaikainen Rosetta kuitenkin lähettää Rosetta-järjestelmäpalvelulle prosessien välisen kommunikaation (IPC) kyselyn, joka kysyy, onko senkertaiselle suoritettavalle levytiedostolle saatavilla AOT-käännös. Jos se löytyy, Rosetta-palvelu antaa viittauksen kyseiseen käännökseen ja se kuvataan prosessiin ja suoritetaan. Suorittamisen aikana kernel vaatii käännösartefaktin koodihakemistotiivisteet, jotka on todennettu allekirjoituksella, jonka juuri on laitekohtaisessa allekirjoitusavaimessa. Alkuperäisen x86_64-levytiedoston koodihakemiston tiivisteet eivät ole mukana tässä prosessissa.
Käännetyt artefaktit tallennetaan tietosäiliöön, johon pääsee ajon aikana ainoastaan Rosetta-palvelu. Rosetta-palvelu hallitsee pääsyä välimuistiinsa jakamalla yksittäisille käännösartefakteille kirjoitussuojattuja tiedostokuvaajia. Tämä rajoittaa pääsyä AOT-artefaktien välimuistiin. Palvelun prosessien välinen kommunikaatio ja riippuvuusjalanjälki pidetään tarkoituksellisesti hyvin suppeina sen hyökkäyspinnan rajoittamiseksi.
Jos alkuperäisen x86_64-levytiedoston koodihakemiston tiiviste ei vastaa AOT-käännösartefaktin allekirjoitukseen koodattua, tätä tulosta kohdellaan kuin epäkelpoa koodin allekirjoitusta ja toimitaan sen mukaisesti.
Jos etäprosessi kyselee kerneliltä AOT-käännetyn suoritettavan tiedoston oikeuksia tai muita koodin identiteettiominaisuuksia, sille palautetaan alkuperäisen x86_64-levytiedoston identiteettiominaisuudet.
Staattisen luottamusvälimuistin sisältö
macOS 11:ssä tai uudemmassa on moniarkkitehtuuriset Mach-binäärit, joissa on osat x86_64- ja arm64-tietokonekoodeista. Apple siliconilla varustetun Macin käyttäjä voi päättää suorittaa x86_64-järjestelmäbinääriä Rosetta-putken kautta esimerkiksi ladatakseen liitännäisen, josta ei ole natiivi-arm64-versiota. Tämän lähestymistavan tukemiseksi macOS:n mukana tuleva staattinen luottamusvälimuisti sisältää yleensä kolme koodihakemiston tiivistettä jokaiselle Mach-O-tiedostolle:
Koodihakemiston tiiviste arm64:lle
Koodihakemiston tiiviste x86_64:lle
Koodihakemiston tiiviste x86_64-puolen AOT-käännökselle
Rosettan AOT-kääntäminen on determinististä sikäli, että samasta syötteestä tulee aina samanlainen tuotos riippumatta kääntämisen ajankohdasta tai siihen käytetystä laitteesta.
macOS:n koonnin aikana jokaiselle Mach-O-tiedostolle tehdään Rosettan AOT-käännös kyseisen macOS-version käännösputkessa, ja saatava koodihakemiston tiiviste tallennetaan luottamusvälimuistiin. Tehokkuussyistä varsinaisia käännettyjä tuotteita ei toimiteta käyttöjärjestelmän mukana. Ne muodostetaan uudelleen käyttäjän pyytäessä niitä.
Kun x86_64-levytiedosto suoritetaan Apple siliconilla varustetussa Macissa, mikäli kyseisen levytiedoston koodihakemiston tiiviste on staattisessa luottamusvälimuistissa, tulokseksi saatavan AOT-artefaktin koodihakemiston tiivisteen odotetaan myös olevan staattisessa luottamusvälimuistissa. Tällaisia tuotteita ei allekirjoiteta laitekohtaisella avaimella, koska allekirjoitusauktoriteetti perustuu Applen suojattuun käynnistysketjuun.
Allekirjoittamaton x86_64-koodi
Apple siliconilla varustettu Mac ei salli natiivin arm64-koodin suorittamista ilman siihen liitettyä kelvollista allekirjoitusta. Tämä allekirjoitus voi yksinkertaisimmillaan olla ad hoc ‑allekirjoitus (vrt. codesign(1)
), jossa ei ole mitään oikeaa identiteettitietoa epäsymmetrisen avainparin salaisesta puolesta (se on yksinkertaisesti binääritiedoston todentamaton mittaus).
Binäärien yhteensopivuuden vuoksi käännetyn x86_64-koodin suorittaminen Rosettan kautta sallitaan ilman mitään allekirjoitustietoa. Tälle koodille ei välitetä määrättyä identiteettiä laitekohtaisessa Secure Enclave ‑allekirjoituksessa, ja se suoritetaan täsmälleen samoilla rajoituksilla kuin natiivi allekirjoittamaton koodi suoritetaan Intel-pohjaisessa Macissa.