Wo liegt mein Fehler? g++ mit -e (--entry)



  • Hallo,
    ich verwende folgenden Code mit dem Kommando g++ -e newMain main.cpp und dennoch wird die alternative Main nicht angenommen.
    Code:

     #include <cstdlib>
    #include <iostream>
    
    int main(int argc, char** argv) {
    cout << "Old" << endl;
    return 0;
    }
    
    int newMain(int argc, char** argv) {
    cout << "New" << endl;
    return main(argc, argv);
    }
    

    Ausgabe:

     Old
    

    ...sollte sein:

    New
    Old
    

    Kompilerwarnung, die das wahrscheinlich erklärt (aber nicht wie man das behebt):

    /usr/bin/ld: warning: cannot find entry symbol newMain; defaulting to 00000(...)
    

    Hat Jemand eine Idee woran es liegt? Vlt. zu viel "Normale"-Optimierung? g++ ist Version 7.3.0

    Danke,
    Simonmicro



  • extern ”C” int newMain ...?



  • Hallo,

    das könnte am Name Mangling liegen. Allerdings glaube ich nicht, dass das an sich eine erfolgversprechende Strategie ist, da main selbst aus Linkersicht gar nicht der Einstiegspunkt ist, wie du erkennen kannst, wenn du mal g++ -e main main.cpp ausprobierst.



  • Genau, der Standardeinstiegspunkt ist _start, s.a. is there a GCC compiler/linker option to change the name of main?



  • @manni66 Diese Modifikation führt zwar zu einer erfolgreichen Kompilierung, jedoch stürzt das Programm darauf mit einem Segmentation fault ab.
    @Bashar g++ -e main main.cpp klappt zwar (auch ohne die Meldung von ld), jedoch stürzt das Programm darauf mit einem Segmentation fault ab.
    @Th69 Ja, das ist zwar eine Alternative, jedoch nicht mein Ziel. Dieses besteht daran exakt diese Option zu verwenden (oder ähnliche Features, welche keine Modifikation der originalen main() erfordern, sondern alternativen Code davor und danach ausführen...).



  • Darf ich fragen, warum du das machen willst? Kann man dein Problem nicht anders lösen? Um einen anderen Einsprungspunkt als main haben zu wollen braucht man mMn scherwiegende Gründe.



  • @simonmicro: Du scheinst immer noch nicht verstanden zu haben, daß main nicht der Standardeinstiegspunkt ist, den du mittels "-e" zu ändern versuchst (du hast anscheinend den Link nicht vollständig gelesen).

    Hier noch zwei weitere Links:



  • @DocShoe Das Ziel ist es eine beliebige C++ Anwendung zu haben und, ohne deren Quellcode direkt zu verändern, jeweils eine eigene Funktion vor und nach Ausführung von main() zu haben. Diese eigenen Funktionen können ja per Forward angekündigt werden und ans Ende der main.cpp (o.Ä.) gehängt werden. Ich möchte nicht den Code direkt in der main manipulieren, da ich nicht von einer angemessenen Formatierung/Zeilenumbrüchen etc. ausgehen möchte. Dabei sollen aber argv und argc erhalten bleiben!

    @Th69 Ich denke jetzt habe ich gemerkt, dass _start() die interne Vorbereitung zur Vorbereitung(Argumente vorbereiten etc.) von main() ist, und damit nicht mein Ziel.

    Bestenfalls sollte dies ohne die beschriebene Veränderung des bestehenden Codes geschehen. Zugegebenermaßen werden wohl Zeilen nachgereicht werden müssen - ohne dass die bestehenden Funktionen berührt werden...



  • @simonmicro sagte in Wo liegt mein Fehler? g++ mit -e (--entry):

    @DocShoe Das Ziel ist es eine beliebige C++ Anwendung zu haben und, ohne deren Quellcode direkt zu verändern, jeweils eine eigene Funktion vor und nach Ausführung von main() zu haben. Diese eigenen Funktionen können ja per Forward angekündigt werden und ans Ende der main.cpp (o.Ä.) gehängt werden. Ich möchte nicht den Code direkt in der main manipulieren, da ich nicht von einer angemessenen Formatierung/Zeilenumbrüchen etc. ausgehen möchte. Dabei sollen aber argv und argc erhalten bleiben!

    ?
    Per forward ankündigen? angemessene Formatierung? Zeilenumbrüche?



  • @DocShoe: Er meint wohl einfach eine "forward declaration". Er möchte wohl per eigenem Programm den bestehenden Source-Code eines anderen Programms verändern.

    @Simonmicro: Lies dir mal Write a C [or C++] program without main function durch, um ein paar Anregungen zu kriegen, wie du vor der main Code ausführen kannst (analog dann auch für "nach der main", z.B. mittels atexit).



  • Also ich habe da echt Verständnisprobleme, was TE eigentlich erreichen möchte.
    Er möchte bei Programmstart "einer beliebigen C++ Anwendung" nicht in main springen, sondern eine andere Funktion, die vor und nach der "echten" main eine Prolog- und Epilogfunktion aufruft. Und das ohne den Quelltext zu verändern, aber dafür neu linken?! Hört sich stark danach an das iwie anders zu lösen. Vielleicht hilft da ein konkretes Beispiel weiter.



  • @DocShoe Man stelle sich eine solche Schönheit vor (wie soll man hier bitte die main manipulieren, ohne aufwendig zu versuchen die Formatierung bezubehalten?):

    int main() {/*Ganz langer Code in EINER Zeile*/}
    (M)ein Skript würde hier den "Vor-der-Main"-Code einbauen...
    
    int main() { /*Ganz langer Code in EINER Zeile*/
    (M)ein Skript würde hier den "Vor-der-Main"-Code einbauen...
    //Ganz langer Code
    }
    

    Und ja, ich meinte eine "forward declaration"...

    @Th69 Gute Ideen! Man könnte mit der static Pre-Main die atexit Funktionen registrieren lassen und den gewünschten Code Ausführen lassen. Das einzige was ich mir noch wünsche, wäre eine Idee, wie man bei dem static-Workaround noch an die Argumente käme - argv und argc...

    @DocShoe Weil du es gerade schreibst... Ich habe eine X-Beliebigen Code, welcher dank eines .sh Skripts speziell kompiliert werden soll (...), dabei sollen dann (zur Laufzeit) z.B. weitere Kommandozeilenparameter abgefragt werden können um z.B. einen "Vor-der-Main"-Timer zu steuern, oder die return-Codes direkt zu interpretieren. Ich möchte dabei die eigentlichen Funktionen nicht anfassen, da ich ja nicht weiß, wie schrecklich der Autor formatiert - sonst füge ich meine Modifikationen noch so ein, dass der Code zerstört wird o.Ä... Die Quellcodes sind natürlich vorhanden, da ich das alles ja kompilieren möchte...



  • Aahhh... jetzt verstehe ich das. Ihr habt eine Art Präprozessor, der, je nach Konfiguration, bestimmte Funktionalität ergänzt. Und bevor du jetzt was in den Quelltext einfügst und aufgrund irgendwelcher seltsamen Quelltextformatierung den Quelltext zerstörst möchtest du vor und nach der main Funktion eigene Funktionen aufrufen, die am besten auch noch die Kommandozeilenparameter mitbringen?
    Muss das plattformunabhängig sein oder auch darf´s auch plattformspezifisch sein? Sind DLLs eine Option?



  • Ich habe noch einen interessanten Artikel gefunden: Linux x86 Program Start Up or - How the heck do we get to main()?

    Und in der Antwort zu "Alternative way to obtain argc and argv of a process" wird ein Weg gezeigt, wie man (evtl.) selber an die Kommandozeilenparameter (Argumente) kommt (wenn auch mit keiner Garantie).
    Eine weitere Antwort dadrin benutzt Prozess "proc file system".



  • Mal blöd gefragt, kann man das tool, welches den code erzeugt den du anpassen sollst, nicht anpassen, dass zu mindestens der main() part günstiger für deine Anpassungen ist?
    Das wäre aus meiner sicht deutlich einfach als jetzt irgendwie durch hacks da was zurecht zu biegen.

    Falls eine Anpassung am generator des codes nicht möglich sein sollte hätte ich da eine Idee.
    Wenn ich das ganze richtig verstanden habe sollst du den code, der aus dem Generator rausfällt mit zusätzlicher funktionalität ausstatten.
    Und aus diesem modifizierten code wird dann das Programm erzeugt.
    Wenn du eh am code "rumfummelst" wiso benennst du die vorhandene main() methode nicht einfach um und fügst deine main hinzu welche dann die umbenannte original main() methode aufruft.

    int main(int argc,  char**argv){/*code*/}
    

    ->

    int orig_main(int argc,  char**argv){/*code*/}
    int main(int argc, char**argv)
    {
        /*pre code*/
       int returnVal = orig_main(argc, argv);
       /* post code */
       return returnVal;
    }
    


  • Stimmt, man könnte sogar einfach den bestehenden Source-Code über die Kompileroptionen mit dem Define -Dmain=orig_main kompilieren und dann in einer neuen Source-Datei die neue main definieren.



  • @DocShoe

    1. Ja, genau das.
    2. Es sollte plattformunabhängig sein, zwar sind dll/so schöne Optionen, jedoch abhängig vom System.

    @Th69
    Auch hier - super Ideen! Ich habe selbst schon an direkten ASM-Eingriff gedacht, verwarf es aber aufgrund meiner fehlender Kenntnisse / Zeit. Die Möglichkeit von /proc hatte ich schlichtweg nicht bedacht! Ich habe zwar schon öfters darüber Daten abgefragt, jedoch war mir die Option der cmdline für ein Programm nicht aufgefallen.
    @firefly Jaaa... Was wäre, wenn main() irgendwo anders (ggf. andere Datei, oder gar .o) refernziert wird? Die Lösung von Th69 mit der Prepocessor-Option macht diese Arbeit des Findens und Korrigierens automatisch.
    @Th69 *Geistesblitz*

    Meine finale Lösung sieht nun so aus:

    1. Kompilierung des Originalcodes mit -Dmain=orig_main in .o
    2. Generieren / Erstellen einer neuen Datei mit neuer main() - diese wird die Post-Main-Funktionen via atexit() registrieren und die Argumente (Programmparameter) weiter verarbeiten. Danach erfolgt der Aufruf der originalen main().
    3. Rekompilierung mit dem neuen Quellcode und den .o.
    4. Voilá!

    Sollte ich noch Probleme kriegen, melde ich mich! Vielen, vielen dank!
    Ihr habt echt klasse Ideen / Arbeit geleistet,
    Simonmicro



  • @simonmicro Es war nur ein Beispiel wie es im endeffekt aussehen könnte 😉
    Ob das jetzt durch text ersetzung im code selbst oder über den preprocessor, ist dann doch egal.



  • @Simonmicro: Würdest du uns noch verraten, was du genau einkompiliert hast?



  • @Th69 Nun, reinkompiliert wird ein Timer, bevor das Programm startet - ebenso ein Listener auf eine Datei, um das Programm bei deren Modifikation sofort beendet wird. Da der eigentliche Programmteil potentieller Schadcode ist erschien mir das als notwendig. Ich plane das Programm danach auf ASM-Ebene durch "Sinnfreien ASM-Code" unkenntlich zu machen. Mal sehen, ob das alles so klappt. Ist ja auch nur eine zufällige Idee...


Anmelden zum Antworten