Soluzione alternativa per l’accesso alla memoria ARM non sincronizzata

Devo portare il codice sorgente da una piattaforma ARM che esegue Linux. Sfortunatamente ho incontrato problemi di accesso alla memoria non allineati. L’origine utilizza cast di puntatori e accesso pesante.

Il codice come quello qui sotto si è diffuso sopra il codebase come un virus. Sono in grado di individuare le posizioni problematiche grazie all’opzione della riga di comando gcc -Wcast-align , ma ci sono oltre un migliaio di istanze da esaminare.

 u = (IEC_BOOL); (((*(IEC_LINT*)pSP).H < bH) || (((*(IEC_LINT*)pSP).H == bH) && ((*(IEC_LINT*)pSP).L > u); *(IEC_DWORD OS_SPTR *)pSP = (IEC_DWORD)(*(IEC_DWORD OS_SPTR *)pSP < bL))) ? 1 : 0); u = (IEC_BYTE)((*(IEC_REAL*)pSP >= b) ? 1 : 0); 

Usando echo 2 > /proc/cpu/alignment su fa sì che il kernel di Linux risolva i problemi, ma le prestazioni dell’applicazione sono degradate a un punto che non è più accettabile.

Ho cercato in rete qualcosa come una parola chiave __unaligned o __packed per il compilatore GCC (v4.4.1), ma al momento non è ancora disponibile.

Ho pensato che molte delle linee di codice poblematic potevano essere corrette con una regexp / replace più o meno complessa, ma ora, dopo averlo fatto per un po ‘, vedo che anche questo approccio richiederà enormi quantità di lavoro noioso.

Avete qualche suggerimento su come ottenere questo lavoro? Penso che un plugin del compilatore gcc 4.5 sarebbe eccessivo, ma c’è qualcosa di meglio delle espressioni regolari? quali altri suggerimenti puoi trovare? Non necessariamente tutte le istanze del problema devono essere corrette poiché posso ancora contare sul kernel per alcuni casi più rari.

C’è __attribute__((__packed__)) che potrebbe aiutare in alcuni casi, ma penso davvero che questo codice dovrebbe essere ripulito piuttosto prima, perché è probabile che impiegherai più tempo a risolvere i problemi di quanto ci vorrebbe per risolverlo una volta per tutte.

Wow, questo è un disastro impuro. Giocherellare con il compilatore non ti porterà da nessuna parte. Il codice è illegale su TUTTE le architetture, ma funziona solo su alcune (ad esempio x86). Fisserei il codice stesso.

Purtroppo non c’è un modo carino per farlo. Tuttavia, potresti ottenere un lungo cammino con un lungo elenco di ricerche e sostituzioni, quindi correggere manualmente il resto. Vorrei iniziare rimuovendo le dichiarazioni di quei tipi di dati, quindi se compilate qualsiasi codice che avete perso, verrà visualizzato un errore. Quindi, cerca e sostituisci snippet come “* (IEC_DWORD OS_SPTR *) pSP =” con “set_dword (pSP,” . Crea una funzione inline “set_dword” per fare la cosa giusta. Procedi con il numero di snippet facilmente sostituibili come puoi immaginare: ci sarà ancora una grande quantità da sistemare a mano.

L’unico altro modo in cui posso pensare di farlo sarebbe un plugin per compilatore, come suggerito, e fare in modo che ogni puntatore dell’intera unità di compilazione abbia allineamento 1. Il compilatore quindi caricherà / immagazzinerà tutto il byte. Probabilmente finirà per farlo per qualcosa di più del semplice codice che hai inteso. Questo probabilmente non è così facile da realizzare come sembra.

Possiamo supporre che il problema derivi dal fatto che ARM è una macchina a 32 bit e la scatola Linux gira in modalità a 64 bit, in alternativa, il codice potrebbe presumere che sia in esecuzione su una macchina a 16 bit.

Un modo sarebbe quello di guardare la struttura sottostante a cui si accede. I membri “H” e “L” potrebbero essere tipi a 32 bit a cui si accede come se fossero 64 bit.

Prova a modificare i tipi di L e H per far sì che il codice si comporti meglio.

(Certamente, questa è una pugnalata al nulla, dato che il frammento di codice non rivela i dettagli dell’applicazione, né delle strutture sottostanti.)