Codi independent de la posició

codi d'instrucció de màquina que s'executa correctament independentment d'on es trobi a la memòria

En informàtica, el codi independent de la posició (PIC) o executable independent de la posició (PIE) és un cos de codi màquina que, col·locat en algun lloc de la memòria primària, s'executa correctament independentment de la seva adreça absoluta. El PIC s'utilitza habitualment per a biblioteques compartides, de manera que el mateix codi de biblioteca es pot carregar en una ubicació de l'espai d'adreces de cada programa on no es solapa amb una altra memòria utilitzada per, per exemple, altres biblioteques compartides. PIC també es va utilitzar en sistemes informàtics antics que no tenien una MMU, de manera que el sistema operatiu pogués mantenir les aplicacions allunyades les unes de les altres fins i tot dins de l'espai d'adreces únic d'un sistema sense MMU.[1]

El codi independent de la posició es pot executar a qualsevol adreça de memòria sense modificació. Això difereix del codi absolut, que s'ha de carregar en una ubicació específica per funcionar correctament, i del codi localitzable en temps de càrrega (LTL), en què un enllaçador o carregador de programes modifica un programa abans de l'execució, de manera que només es pot executar des d'una ubicació de memòria determinada. La generació de codi independent de la posició és sovint el comportament predeterminat per als compiladors, però poden posar restriccions a l'ús d'algunes característiques del llenguatge, com ara no permetre l'ús d'adreces absolutes (el codi independent de la posició ha d'utilitzar l'adreçament relatiu). Les instruccions que es refereixen directament a adreces de memòria específiques de vegades s'executen més ràpid, i substituir-les per instruccions d'adreçament relatiu equivalents pot resultar en una execució lleugerament més lenta, tot i que els processadors moderns fan que la diferència sigui pràcticament insignificant.[2]

Història

modifica

Als primers ordinadors com l'IBM 701 (29 d'abril de 1952) o l'UNIVAC I (31 de març de 1951) el codi no era independent de la posició: cada programa es va crear per carregar-se i executar-se des d'una adreça particular. Els primers ordinadors no tenien un sistema operatiu i no eren capaços de fer múltiples tasques. Els programes es carregaven a l'emmagatzematge principal (o fins i tot s'emmagatzemaven al tambor magnètic per a l'execució directament des d'allà) i s'executaven d'un en un. En aquest context operatiu, el codi independent de la posició no era necessari.

Detalls tècnics

modifica

Les trucades de procediment dins d'una biblioteca compartida es fan normalment a través de petits talons de taula d'enllaç de procediments, que després criden a la funció definitiva. Això permet notablement que una biblioteca compartida hereti determinades trucades de funcions de biblioteques carregades anteriorment en lloc d'utilitzar les seves pròpies versions.[3]

Les referències de dades del codi independent de la posició es fan generalment de manera indirecta, mitjançant taules de compensació global (GOT), que emmagatzemen les adreces de totes les variables globals a les quals s'accedeix. Hi ha un GOT per unitat de compilació o mòdul d'objecte, i es troba a un desplaçament fix del codi (tot i que aquest desplaçament no es coneix fins que la biblioteca està enllaçada). Quan un enllaçador enllaça mòduls per crear una biblioteca compartida, fusiona els GOT i estableix els desplaçaments finals al codi. No cal ajustar els desplaçaments en carregar la biblioteca compartida més tard.

Les funcions independents de la posició que accedeixen a dades globals comencen determinant l'adreça absoluta del GOT donat el seu propi valor de comptador de programa actual. Sovint, això pren la forma d'una trucada de funció falsa per obtenir el valor de retorn a la pila (x86), en un registre estàndard específic (SPARC, MIPS) o un registre especial (POWER / PowerPC / Power ISA), que després pot es traslladarà a un registre estàndard predefinit, o per obtenir-lo en aquest registre estàndard (PA-RISC, Alpha, ESA/390 i z/Architecture). Algunes arquitectures de processadors, com el Motorola 68000, Motorola 6809, WDC 65C816, Knuth's MMIX, ARM i x86-64 permeten fer referència a dades per offset des del comptador del programa. Això està dirigit específicament a fer que el codi independent de la posició sigui més petit, menys exigent de registre i, per tant, més eficient.

Executables independents de la posició

modifica

Els executables independents de la posició (PIE) són binaris executables fets completament a partir de codi independent de la posició. Tot i que alguns sistemes només executen executables PIC, hi ha altres motius pels quals s'utilitzen. Els binaris PIE s'utilitzen en algunes distribucions de Linux centrades en la seguretat per permetre que PaX o Exec Shield utilitzin l'aleatorització del disseny de l'espai d'adreces (ASLR) per evitar que els atacants sàpiguen on es troba el codi executable existent durant un atac de seguretat mitjançant explotacions que es basen en conèixer el desplaçament del codi executable al binari, com ara atacs de retorn a libc. (El nucli oficial de Linux des del 2.6.12 de 2005 té un ASLR més feble que també funciona amb PIE. És feble perquè l'aleatorietat s'aplica a unitats de fitxer ELF senceres.) [4]

El macOS i iOS d'Apple admeten completament els executables PIE a partir de les versions 10.7 i 4.3, respectivament; s'emet un avís quan s'envien executables iOS que no són de PIE per a l'aprovació a l'App Store d'Apple, però encara no hi ha cap requisit dur, i les sol·licituds que no siguin PIE no es rebutgen.

Referències

modifica
  1. «Position-Independent Code - Linker and Libraries Guide» (en anglès). [Consulta: 9 desembre 2023].
  2. «All you need to know about Position-Independent Code and Data (PIC and PID)» (en anglès), 25-04-2022. [Consulta: 9 desembre 2023].[Enllaç no actiu]
  3. «Position-independent code» (en anglès americà). [Consulta: 9 desembre 2023].
  4. Lettieri, G. «Address Space Layout Randomization» (en anglès).