2013-03-11 6 views
16

PowerPC-Zweigstellen haben nur 24 Bits für den Zieloffset verfügbar. Wenn der Textabschnitt zu groß wird, können Zweige an einem Ende die Ziele nicht erreichen das andere. Es gibt eine längere Befehlsfolge, die weiter entfernte Ziele erreichen kann (der Offset beträgt 32 statt 24 Bits), aber GCC verwendet sie standardmäßig nicht, es sei denn, Sie übergeben die Option -mlongcall. Aber auch mit dieser Option auf, noch GCC erzeugt kurze Anrufe für bestimmte Funktionen, nämlich operator new und operator deleteGCC weigert sich, lange Aufrufe für Operator neu/Löschen auf PowerPC auszugeben

Zum Beispiel gegeben diesen Code:

extern void foo(); 

int main(int argc, char** argv) { 
    foo(); 
    new char; 
} 

Ein normaler Lauf der GCC die Assembly generiert:

bl _Z3foov // void foo() 
bl _Znwj // operator new(unsigned int) 

Lauf GCC mit der -mlongcall Option generiert:

lis r9, [email protected] 
addi r9, r9, [email protected] 
mtctr r9 
bctrl 
bl _Znwj 

Die ersten vier Anweisungen sind wie erwartet ein langer Anruf an foo(), aber der Aufruf an operator new ist unverändert. Aufrufe in zufällige libc- und libstdC++ - Funktionen werden alle wie erwartet in lange Aufrufe konvertiert. Warum enden die Anrufe operator new und operator delete immer noch als bl Anweisungen? Gibt es eine Möglichkeit, GCC dazu zu zwingen, auch lange Anrufe zu machen? Ich benutze GCC 4.7.2 auf einem 64-Bit PowerPC Fedora-Rechner (obwohl ich 32-Bit baue)

+2

Welche Version von GCC? Haben Sie auf http://gcc.gnu.org/bugzilla/ einen Fehlerbericht erstellt? Hast du es mit dem letzten GCC (4.7.2 und bald 4.8) versucht? –

+5

Kneif mich, es ist spät hier, und vielleicht träume ich schon. Oder habe ich gerade eine gute Frage gefunden? –

+2

Nur wundernd, ist es das gleiche, wenn Sie einen Ersatz definieren 'void * operator new (std :: size_t);'? – aschepler

Antwort

3

Es scheint, die g ++ Toolchain hat eine Art Bug, wie es die acht "austauschbaren" Funktionen nennt der C++ - Standardbibliothek in Ihrer Architektur, wenn diese Funktionen nicht tatsächlich durch Benutzercode ersetzt werden.

Tragbares Ersatz-Implementierung für alle acht ist:

#include <memory> 
#include <cstdlib> 

// May never return a null pointer. 
void* operator new(std::size_t size) { 
    void* p = std::malloc(size, 1); 
    while (!p) { 
     std::new_handler handler = std::get_new_handler(); 
     if (handler) { 
      handler(); 
     } else { 
      throw std::bad_alloc(); 
     } 
     // A handler is only allowed to return if it did something to make more 
     // memory available, so try again. 
     p = std::malloc(size, 1); 
    } 
    return p; 
} 

void operator delete(void* p) noexcept { 
    if (p) std::free(p); 
} 

void* operator new(std::size_t size, const std::nothrow_t&) noexcept { 
    void* p = nullptr; 
    try { 
     p = operator new(size); 
    } catch(...) {} 
    return p; 
} 

void operator delete(void* p, const std::nothrow_t&) noexcept { 
    operator delete(p); 
} 

// May never return a null pointer. 
void* operator new[](std::size_t size) { 
    return operator new(size); 
} 

void operator delete[](void* p) noexcept { 
    operator delete(p); 
} 

void* operator new[](std::size_t size, const std::nothrow_t& nt) noexcept { 
    return operator new(size, nt); 
} 

void operator delete[](void* p, const std::nothrow_t& nt) noexcept { 
    operator delete(p, nt); 
} 
0

Wenn wir diese Funktion unter Pragma long_calls definieren können oder Lang Rufattribut innerhalb dieser Funktion deklarieren, können wir GCC zwingen, sie lange telefonieren wie Gut. Checkout GCC-Optionen.

Verwandte Themen