2009-06-30 11 views
15

compilazione di un modulo del kernel a 32 bit risultati del kernel Linux in__udivdi3 indefinito - come trovare il codice che lo utilizza?

"__udivdi3" [mymodule.ko] undefined! 
"__umoddi3" [mymodule.ko] undefined! 

Tutto è bene su sistemi a 64 bit. Per quanto ne so, la ragione di ciò è che la divisione integer a 64 bit e il modulo non sono supportati all'interno di un kernel Linux a 32 bit.

Come trovare il codice che rilascia le operazioni a 64 bit. Sono difficili da trovare manualmente perché non riesco facilmente a verificare se un "/" è largo 32 bit o 64 bit. Se le funzioni "normali" non sono definite, posso annullarle, ma qui non è possibile. C'è un altro buon modo per cercare i riferimenti? Qualche tipo di "codice macchina grep"?

Il modulo è composto da alcune migliaia di righe di codice. Non riesco davvero a controllare ogni riga manualmente.

risposta

19

Innanzitutto, è possibile eseguire la divisione a 64 bit utilizzando la macro do_div. (Notare il prototipo è uint32_t do_div(uint64_t dividend, uint32_t divisor) e che "dividend" possono essere valutati più volte.

{ 
    unsigned long long int x = 6; 
    unsigned long int y = 4; 
    unsigned long int rem; 

    rem = do_div(x, y); 
    /* x now contains the result of x/y */ 
} 

Inoltre, si dovrebbe essere in grado di trovare o utilizzo di long long int (o uint64_t) tipi nel codice, o in alternativa, si può costruire il modulo con la bandiera -g e utilizzare objdump -S per ottenere una fonte di smontaggio annotata

nota:. l'uso questo vale per i kernel 2.6, non ho controllato per nulla inferiore

+9

per aggiungere un po 'di informazioni, do_div() è definito nell'intestazione . –

+1

Sembra piuttosto ridicolo che Linux insista nel farti usare una brutta funzione per dividere, piuttosto che implementare semplicemente '__udivdi3' ecc. Sono facili da implementare, e se lo fai in asm, saranno molto più efficienti di le versioni di libgcc (forse 2-3 volte più veloce). –

+0

@WilliBallenthin anche dopo aver usato , affrontare questo problema.so qualcuno mi suggerisce cosa fare per risolvere questo problema? –

2

Dopo la fase di compilazione, si dovrebbe essere in grado di ottenere alcuni assembly documentati e vedere se tali funzioni sono state chiamate. Prova a fare casino con CFLAGS e aggiungi i flag -S. La compilazione dovrebbe terminare in fase di assemblaggio. È quindi possibile grep per la chiamata della funzione all'origine nel file assembly.

1

In realtà, la divisione intero a 64 bit e il modulo sono supportati in un kernel Linux a 32 bit; tuttavia, è necessario utilizzare i macro corretti per farlo (quali dipendono dalla versione del kernel, poiché recentemente sono stati creati nuovi migliori IIRC). Le macro faranno la cosa giusta nel modo più efficiente per qualsiasi architettura per cui si sta compilando.

Il modo più semplice per trovare dove vengono utilizzati è (come indicato nella risposta di @ shodanex) per generare il codice assembly; IIRC, il modo per farlo è qualcosa come make directory/module.s (insieme con tutti i parametri che devi già passare a make). Il prossimo modo più semplice è quello di smontare il file .o (con qualcosa come objdump --disassemble). Entrambe le modalità ti daranno le funzioni in cui vengono generate le chiamate (e, se sai leggere l'assembly, un'idea generale di dove si trova la divisione all'interno della funzione).

Problemi correlati