2016-06-23 13 views
6

Ich mache einige Reverse Engineering-Aufgaben in Richtung Binärdateien auf 32-bit x86 Architektur.Speicherzuordnungsoptimierung: von Heap zu Stack

Vor kurzem fand ich einige interessante Optimierungen von C Quellcode Assemblerprogramm.

Zum Beispiel des Original-Quellcode ist wie (dieser Quellcode von openssl library ist):

powerbufFree = (unsigned char *)malloc(powerbufLen); 

Und nach der Kompilierung (gcc version 4.8.4 -O3), der Assembler-Code ist wie folgt:

807eaa0: cmp eax, 0xbff       # eax holds the length of the buf. 
807eaa5: mov dword ptr [ebp-0x68], eax   # store the length of powerbuf on the stack 
807eaa8: jnle 0x807ec60       # 0x807ec60 refers to the malloc 
807eaae: mov edx, eax 
807eab0: add eax, 0x5e 
807eab3: and eax, 0xfffffff0 
807eab6: sub esp, eax 
807eab8: lea eax, ptr [esp+0x23] 
807eabc: and eax, 0xffffffc0 
807eabf: add eax, 0x40 
807ead3: mov dword ptr [ebp-0x60], eax # store the base addr of the buf on the stack. 

Zu meiner Überraschung ist der Buf tatsächlich auf dem Stapel verteilt !!! Es scheint wie eine Optimierung für Heap-Allokator für mich, aber ich bin mir nicht sicher.

So, hier ist meine Frage, hat die obige Optimierung (malloc -> Stack Allocation) für jeden familar scheint? Macht das Sinn? Könnte jemand eine Anleitung/Spezifikation für eine solche Optimierung bereitstellen?

+0

wo ist der malloc Anruf \ –

+1

Das erinnert mich sehr an Escape-Analyse in neueren JVMs?. https://en.wikipedia.org/wiki/Escape_analysis Wenn der Speicher nie außerhalb des Funktionsaufrufs leben wird, kann er sicher vom Stapel zugewiesen werden. Wenn Sie Platz in Ihrem Stapel haben, wird dies ein viel schnelleres Allok/Frei-Paar von Operationen sein. – Sam

+0

Ich denke, Heap ist eine allgemeine Baumstruktur. Beim Durchlaufen des Heapspeichers mit der Suchmethode Depth FIrst werden die Elemente nacheinander in der Reihenfolge eines Stapels aufgerufen. –

Antwort

5

Vom source of bn_exp.c:

0634 #ifdef alloca 
0635  if (powerbufLen < 3072) 
0636   powerbufFree = alloca(powerbufLen+MOD_EXP_CTIME_MIN_CACHE_LINE_WIDTH); 
0637  else 
0638 #endif 
0639  if ((powerbufFree=(unsigned char*)OPENSSL_malloc(powerbufLen+MOD_EXP_CTIME_MIN_CACHE_LINE_WIDTH)) == NULL) 
0640   goto err; 

Beachten Sie, dass 0xbff bis 3071. Auf Systemen gleich ist, die es unterstützen, alloca nicht Zuteilung stapeln. Dies gilt für die GNU version, die von Linux verwendet wird, und BSD implementations diese API von 32V UNIX kopiert von AT & T (according to FreeBSD).

Sie schaute nur auf Linie 639. Aber wenn alloca definiert ist, dann ist der C-Code übereinstimmt, um die Assembly auf.

Die Optimierung selbst wird oft verwendet, um die Kosten der für einen temporären Puffer mit malloc zu vermeiden, wenn die Zuordnung relativ klein ist. Für C.1999 könnte stattdessen ein VLA verwendet werden (seit C2011 ist VLA ein optionales Merkmal).

Manchmal verwendet die Optimierung nur eine feste Größe Puffer von einer vernünftigen Größe eher klein. Zum Beispiel:

char tmp_buf[1024]; 
char *tmp = tmp_buf; 

if (bytes_needed > 1024) { 
    tmp = malloc(bytes_needed); 
} 
/* ... */ 
if (tmp != tmp_buf) { 
    free(tmp); 
} 
+0

Vielen Dank für Ihre Hilfe ... Ich bin so unvorsichtig in diesem Moment ... – computereasy

Verwandte Themen