2010-11-11 14 views
12

Desidero conoscere la lunghezza della funzione C (scritta da me) in fase di esecuzione. Qualche metodo per averlo? Sembra che sizeof non funzioni qui.Come ottenere la lunghezza di una funzione in byte?

+2

Si prega di definire "la lunghezza della funzione C" ** ** proprio – pmg

+0

intendo la memoria occupata dal codice di questa funzione. – Thomson

+1

Se lo chiedi per lo stesso motivo per cui mi sono interrogato molti anni fa, permettimi di indicare [Scrivere un nuovo Jit] (http://stackoverflow.com/questions/4097301/writing-a-new-jit) –

risposta

13

Non c'è modo in C standard per ottenere la quantità di memoria occupata da una funzione.

0

Non esiste un modo standard per farlo in C o C++. Potrebbero esistere naturalmente modi di implementazione/piattaforma specifici per eseguirlo, ma non sono a conoscenza di alcun

3

In es. Codewarrior, puoi posizionare le etichette attorno a una funzione, ad es.

label1: 
void someFunc() 
{ 
    /* code goes here. */ 
} 
label2: 

e quindi calcolare la dimensione come (int)(label2-label1), ma questa è ovviamente molto compilatore dipendente. A seconda del sistema e del compilatore, potrebbe essere necessario modificare script di linker, ecc.

+0

Non lo sapevo. Divertente. Una specie di. – haylem

+2

C'è un'estensione [GCC simile] (http://gcc.gnu.org/onlinedocs/gcc-4.5.0/gcc/Labels-as-Values.html#Labels-as-Values), usandola potresti in grado di calcolare la dimensione come '&& label2 - && label1' – Hasturkun

+0

Spero che funzioni, ma sembra che non funzioni in Visual C++ (linguaggio C). – Thomson

4

Eseguibili (almeno quelli che hanno informazioni di debug spogliate) non memorizzano le lunghezze di funzione in alcun modo. Quindi non c'è la possibilità di analizzare queste informazioni in autonomia da solo. Se devi manipolare le funzioni, dovresti fare qualcosa con i tuoi oggetti nella fase di collegamento o accedendoli come file dal tuo eseguibile. Ad esempio, è possibile indicare al linker di collegare le tabelle dei simboli come sezione di dati ordinaria nell'eseguibile, assegnare loro un nome e analizzare quando viene eseguito il programma. Ma ricorda, questo sarebbe specifico per il tuo linker e il formato dell'oggetto.

Si noti inoltre, che il layout funzione è anche piattaforma specifica e ci sono alcune cose che rendono il termine "lunghezza funzione" poco chiara:

  1. funzioni possono avere negozio di usato costanti in sezioni di codice subito dopo codice funzione e l'accesso usando l'indirizzamento relativo al PC (i compilatori ARM lo fanno).
  2. Le funzioni possono avere "prolog" e "epilog", che potrebbero essere comuni a più funzioni e quindi trovarsi al di fuori del corpo principale.
  3. Codice funzione può inline altro codice funzione

Tutti possono contare o meno contare lunghezza funzione.

Anche la funzione può essere completamente delineata dal compilatore, quindi perde il suo corpo.

+0

possono ma queste funzioni hanno ancora una lunghezza fissa, si comportano male solo senza quelle dipendenze esterne. Queste funzioni possono essere ricostruite per essere autonome prendendo le loro dipendenze come argomenti, e molte funzioni, specialmente le funzioni di callback, sono esattamente questo. – Dmitry

1

Non esiste alcuna funzione definita all'interno del linguaggio C per restituire la lunghezza di una funzione; ci sono semplicemente troppe variabili coinvolte (compilatore, set di istruzioni di destinazione, file oggetto/formato file eseguibile, impostazioni di ottimizzazione, impostazioni di debug, ecc.). Lo stesso codice sorgente può comportare funzioni di dimensioni diverse per sistemi diversi.

C semplicemente non fornisce alcun tipo di capacità di riflessione per supportare questo tipo di informazioni (sebbene singoli compilatori possano fornire estensioni, come l'esempio Codewarrior citato da sskuce). Se hai bisogno di sapere quanti byte occupa la tua funzione in memoria, dovrai esaminare direttamente l'oggetto generato o il file eseguibile.

sizeof func non funziona perché l'espressione func viene considerata come un puntatore alla funzione, quindi si ottiene la dimensione di un valore di puntatore, non la funzione stessa.

+0

In un compilatore conforme, 'sizeof func' non funziona perché un designatore di funzione non è un operando valido dell'operatore' sizeof'. – caf

+0

@caf: * facepalm * Sì, hai ragione. Sapevo che. Veramente. –

+0

@JohnBode mentre hai ragione che questa informazione non è portabile; il compilatore è ancora ben consapevole di tutti questi fattori in fase di compilazione e il risultato ha perfettamente senso per quella particolare piattaforma. Conoscere la dimensione di una funzione è significativo su quella piattaforma perché consente di memorizzare lo shellcode delle funzioni di "sola lettura", che ha implicazioni molto interessanti e consistenti che non possiamo studiare senza avere una tale caratteristica. – Dmitry

3

L'inizio della funzione è il puntatore di funzione, lo sai già.

Il problema è quello di trovare alla fine, ma che può essere fatto in questo modo:

#include <time.h> 

int foo(void) 
{ 
    int i = 0; 
    ++i + time(0); // time(0) is to prevent optimizer from just doing: return 1; 
    return i; 
} 

int main(int argc, char *argv[]) 
{ 
    return (int)((long)main - (long)foo); 
} 

funziona qui perché il programma ha solo due funzioni, quindi se il codice è ri-ordinato (principale attuate prima pippo) quindi otterrai un calcolo irrilevante (negativo), facendoti sapere che non ha funzionato in questo modo ma che avrebbe funzionato se avessi spostato il codice foo() in main() - solo sottrai la dimensione main() che hai ottenuto con la risposta negativa iniziale.

Se il risultato è positivo, sarà corretto -se non viene eseguito alcun riempimento (sì, alcuni compilatori gonfiano felicemente il codice, sia per l'allineamento che per altri motivi meno ovvi).

Il cast finale (int) (long) è per la portabilità tra codice a 32 bit e a 64 bit (i puntatori di funzione saranno più lunghi su una piattaforma a 64 bit).

Questo è faily portatile e dovrebbe funzionare abbastanza bene.

12

C'è un modo per determinare la dimensione di una funzione. Il comando è:

nm -S <object_file_name> 

Ciò restituirà le dimensioni di ogni funzione all'interno del file oggetto. Consulta le pagine del manuale in GNU usando 'man nm' per raccogliere maggiori informazioni al riguardo.

+0

o objdump, FWIW. – sehe

+0

'nm -S --size-sort -t d | grep 'visualizza la dimensione in base 10 (' -t d' per * decimale *) dei simboli contenenti 'modello' nel nome, ordinati per dimensione. Molto carino. – hdl

12

È possibile ottenere queste informazioni dal linker se si utilizza uno script linker personalizzato. Aggiungi una sezione linker solo per la funzione di data, con i simboli di linker su entrambi i lati:

mysec_start = .; 
*(.mysection) 
mysec_end = .; 

Quindi è possibile assegnare specificamente la funzione a quella sezione. La differenza tra i simboli è la lunghezza della funzione:

#include <stdio.h> 

int i; 

__attribute__((noinline, section(".mysection"))) void test_func (void) 
{ 
    i++; 
} 

int main (void) 
{ 
    extern unsigned char mysec_start[]; 
    extern unsigned char mysec_end[]; 

    printf ("Func len: %lu\n", mysec_end - mysec_start); 
    test_func(); 

    return 0; 
} 

Questo esempio è per GCC, ma qualsiasi toolchain C deve avere un modo per specificare quale sezione assegnare una funzione. Vorrei verificare i risultati confrontandoli con l'elenco degli assembly per verificare che funzioni nel modo che preferisci.

+0

Puoi farlo senza uno script linker personalizzato chiamando la sezione con un nome identificativo C valido, ad esempio 'mysection' invece di' .mysection', e usando '__start_mysection' e' __stop_mysection' invece di 'mysec_start' e' mysec_end '. Il linker definisce automaticamente questi simboli per ogni sezione incontrata. – Janiels

-3

È possibile trovare la lunghezza della funzione C sottraendo gli indirizzi delle funzioni. Lasciatemi fare un esempio

int function1() 
    { 
    } 

int function2() 
{ 
    int a,b; //just defining some variable for increasing the memory size 
    printf("This function would take more memory than earlier function i.e function01 "); 
} 

int main() 
{ 
    printf("Printing the address of function01 %p\n",function01); 
    printf("Printing the address of function02 %p\n",function02); 
    printf("Printing the address of main %p\n",main); 
    return 0; 
} 

Spero che si otterrebbe la risposta dopo la compilazione di esso. Dopo la compilazione potrai vedere la differenza di function01 e function2.

Nota: normalmente c'è una differenza di 16bytes tra una funzione e l'altra.

+0

il tuo esempio non sta dimostrando nulla :) stai solo stampando gli indirizzi delle funzioni! –

1

Basta sottrarre l'indirizzo della funzione dall'indirizzo della funzione successiva. Ma si noti che non può funzionare sul vostro sistema, in modo da utilizzare solo se si sicuri al 100%:

#include <stdint.h> 

int function() { 
    return 0; 
} 

int function_end() { 
    return 0; 
} 

int main(void) { 
    intptr_t size = (intptr_t) function_end - (intptr_t) function; 
} 
Problemi correlati