Welchen Namen hat diese Optimierung?

Programmiersprachen, APIs, Bibliotheken, Open Source Engines, Debugging, Quellcode Fehler und alles was mit praktischer Programmierung zu tun hat.
Antworten
Psycho
Establishment
Beiträge: 156
Registriert: 16.09.2002, 14:23

Welchen Namen hat diese Optimierung?

Beitrag von Psycho »

Hallo,

ich spiel grad an einem Programm, bei dem ich folgende Assembler-Funktionen habe:

Code: Alles auswählen

void __declspec(naked) funktion1()
{
  __asm CALL hauptFunktion;
}
void __declspec(naked) funktion2()
{
  __asm CALL hauptFunktion;
}

void __declspec(naked) hauptFunktion()
{
  /* Jetzt liegt ja der Rücksprungwert bei [esp]
  Je nachdem, welcher Wert das ist, soll unterschiedlich verfahren werden. */
}
Jetzt habe ich ein paar Stunden debuggt, um festzustellen, dass er die Funktionen funktion1 und funktion2 zu einer einzigen Funktion zusammenoptimiert hat. Also funktioniert das unterscheiden nach dem Rücksprungwert nicht mehr, da er ja immer der gleiche ist.
Nach dem Deaktivieren aller Optimierungen lief mein Programm. Aber kann ich die Optimierung auch gezielt abschalten? Ich möchte ja nicht auf alle Optimierungen verzichten.

Alternativ sollte ich meinen Code eventuell auch hierzu umstricken, da das Verfahren oben ja ein ziemliches Rumgehacke ist?!

Code: Alles auswählen

void __declspec(naked) funktion1()
{
  __asm PUSH funktion1;
  __asm CALL hauptFunktion;
}
void __declspec(naked) funktion2()
{
  __asm PUSH funktion2;
  __asm CALL hauptFunktion;
}
void __declspec(naked) hauptFunktion(void *caller)
{
  // Jetzt kann ich nach dem Wert von caller unterscheiden.
}
Benutzeravatar
Schrompf
Moderator
Beiträge: 4864
Registriert: 25.02.2009, 23:44
Benutzertext: Lernt nur selten dazu
Echter Name: Thomas Ziegenhagen
Wohnort: Dresden
Kontaktdaten:

Re: Welchen Namen hat diese Optimierung?

Beitrag von Schrompf »

Unterschiedliche Code-Pfade je nach Rücksprungadresse? Das ist ein ganz ganz übler Hack. Was willst Du damit denn erreichen? Und warum reichst Du die beiden Methoden nicht einfach als Funktionsparameter rein? Oder machst gleich zwei getrennte Funktionen draus?
Früher mal Dreamworlds. Früher mal Open Asset Import Library. Heutzutage nur noch so rumwursteln.
joggel

Re: Welchen Namen hat diese Optimierung?

Beitrag von joggel »

@Psycho:
was erhoffst Du dir davon? Nur so? Rein interessehalber?
Also die 2. Variante macht für mich irgendwie mehr sinn als die erste..... in der ersten sind ja beide Funktionen gleich, klar das er da optimiert!
Benutzeravatar
Krishty
Establishment
Beiträge: 8261
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: Welchen Namen hat diese Optimierung?

Beitrag von Krishty »

Die Optimierung heißt COMDAT-Folding (sozusagen String-Pooling für Programm-Code). Benutz lieber die Version, bei der die Funktionen binär unterschiedlich sind, weil COMDAT-Folding – besonders bei vielen kleinen virtuellen Funktionen und Template-lastigem Quelltext – ziemlich viel bringen kann. Oder – optimal – unterschiedliche Parameter.

Gruß, Ky
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
eXile
Establishment
Beiträge: 1136
Registriert: 28.02.2009, 13:27

Re: Welchen Namen hat diese Optimierung?

Beitrag von eXile »

Man braucht ja nicht unbedingt die Optimierungen für den ganzen restlichen Code deaktivieren:
http://msdn.microsoft.com/en-us/library/chh3fb0k.aspx

Es kann sein, dass dieser Kommentar Müll ist, weil ja das COMDAT-Folding im Linker gemacht wird, und damit der obige Link hier gar nicht anwendbar ist (auch wenn es ja wohl eine globale Optimierung ist). Ich habe es bisher auch nicht ausprobiert - ich stimme in dieser Hinsicht Schrompf zu.

Zweiter Nachtrag: Genau wie Krishty sagte ... ;)
Zuletzt geändert von eXile am 22.10.2010, 14:48, insgesamt 2-mal geändert.
Benutzeravatar
Krishty
Establishment
Beiträge: 8261
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: Welchen Namen hat diese Optimierung?

Beitrag von Krishty »

#pragma optimize schaltet ja nur die /O*-Switches durch, und von denen benutzt (afaik) keiner /OPT:ICF. Das deckt sich damit, dass COMDAT-Folding vom Linker auf ein fertig kompiliertes und optimiertes Programm angewandt wird (es geht ja um die Optimierung der binären Programmrepräsentation, nicht des Programms selber) statt auf einzelne Code-Abschnitte.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
Sternmull
Establishment
Beiträge: 264
Registriert: 27.04.2007, 00:30
Echter Name: Til
Wohnort: Dresden

Re: Welchen Namen hat diese Optimierung?

Beitrag von Sternmull »

Was spricht denn dagegen ein Funktionsargument statt der Funktionsadresse als Bedingung für die unterschiedlichen Code-Pfade zu verwenden?

Hast du mal versucht die Funktionen zu exportieren? Da würde ich eigentlich erwarten das die nicht einfach zusammen gelegt werden.
Benutzeravatar
Krishty
Establishment
Beiträge: 8261
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: Welchen Namen hat diese Optimierung?

Beitrag von Krishty »

Sternmull hat geschrieben:Hast du mal versucht die Funktionen zu exportieren? Da würde ich eigentlich erwarten das die nicht einfach zusammen gelegt werden.
Ins Blaue geraten würde ich sagen, doch. Spricht ja nichts dagegen, dass zwei Exports auf dieselbe Adresse verweisen.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
eXile
Establishment
Beiträge: 1136
Registriert: 28.02.2009, 13:27

Re: Welchen Namen hat diese Optimierung?

Beitrag von eXile »

Ohne zu wissen, was Psycho überhaupt erreichen will, können wir hier ihm auch schlecht andere Lösungsansätze anbieten. Wobei es mich schon interessieren würde, ob ein nop in einer der beiden Funktionen die Funktion bereits für den Linker unterschiedlich erscheinen lässt. ;)
Psycho
Establishment
Beiträge: 156
Registriert: 16.09.2002, 14:23

Re: Welchen Namen hat diese Optimierung?

Beitrag von Psycho »

Hallo,

ich schreibe ein Tool ähnlich wie dieses: API Logger

Ich hooke also verschiedene APIs in einem Zielprozess.
Damit nicht bereits zur Compilezeit in meinem Programm folgendes stehen muss:

Code: Alles auswählen

BOOL __stdcall hooked_SetWindowTextW(HWND, const wchar_t *) { }
möchte ich gerne flexible "Dummies" im Programm haben, die dann für jede beliebige API verändert werden können. Dabei beeinflussen sie die Funktion nicht, sondern loggen nur mit, dass die API aufgerufen wurde.
Im Moment kann ich folgendes in meinem Programm schreiben:

Code: Alles auswählen

// Irgendwo:
#define HOOKED_FUNCTION(functionName)\
FARPROC __declspec(naked) functionName()\
{\
	__asm { CALL hookTemplate1 }\
}
HOOKED_FUNCTION(hooked_SetWindowTextW)

// Später dann
addFunction(hookEntries, TEXT("user32.dll"), "SetWindowTextW", hooked_SetWindowTextW, moduleList, new ParameterFactoryPointer(TEXT("hWnd")), new ParameterFactoryWString(TEXT("string")));
hookEntries ist ein globales Array, in dem alle Hooks gespeichert werden, die Hooks selbst kümmern sich ums Loggen. Klappt wie gesagt auch alles ok, wenn ich die Optimierungen abschalte, aber ich nehme an die Lösung mit dem Parameter müsste funktionieren und ist nicht mehr ganz so hässlich. Ich werde das Makro entsprechend ändern.
Das Problem war ursprünglich, dass ich der hooked_SetWindowTextW natürlich keinen Parameter meiner Klasse HookEntry mitgeben kann, denn die wird ja von außerhalb aufgerufen.
Später soll es möglich sein, dass eine Datei angegeben wird, in der dann zb steht:
BOOL SetWindowTextW(Pointer hWnd, WString string)

und noch zusätzliche Zeilen, so dass dann zur Laufzeit genau die passenden Funktionen gehookt werden. Der große Nachteil bei dem Programm von iDefense ist nämlich in meinen Augen, dass irgendwann irgendjemand alle APIs, die geloggt werden sollen, da ins Programm eingetragen hat.

COMDAT-Folding, jetzt weiß ich Bescheid, danke.
Helmut
Establishment
Beiträge: 237
Registriert: 11.07.2002, 15:49
Wohnort: Bonn
Kontaktdaten:

Re: Welchen Namen hat diese Optimierung?

Beitrag von Helmut »

Wenn du die zu hookenden Funktionen tatsächlich über so eine Textdefinition dynamisch hooken willst wirste nicht drumherum kommen zur Laufzeit Code erzeugen zu müssen. C++ bietet dazu leider keine Sprachwerkzeuge an.
Allerdings muss das ja kein Maschinencode sein, den dein Programm erzeugen muss. C++ Code dynamisch zu erzeugen und in eine DLL zu compilieren ist ziemlich einfach, platformunabhängig und schnell. Man muss halt nur einen Compiler mit zum Programm packen.

Ciao
Helmut
Benutzeravatar
eXile
Establishment
Beiträge: 1136
Registriert: 28.02.2009, 13:27

Re: Welchen Namen hat diese Optimierung?

Beitrag von eXile »

Es reicht bereits aus, zu jeder zu hookenden Funktion zu wissen, wieviele Parameter sie bekommt (in Bytes). Dann einfach die Parameter etwas weiter auf den Stack hochschieben, in den gewonnenen Freiraum die lokalen (zum Loggen notwendigen) Variablen plazieren, und beim Rücksprung hast du dann sowohl deine lokalen Variablen wie auch den Rückgabewert auf dem Stack liegen. Einfach noch loggen, die lokalen Variablen wieder vom Stack runterschmeißen und zurückspringen.

Nachtrag: Vor dem Sprung in die Zielfunktion kannst du alle Parameter loggen, nach dem Rücksprung kannst du den Rückgabewert loggen. Natürlich solltest du tierisch darauf aufpassen, dass du keine Funkionen hookst, die niemals zurückkehren (so etwas gibts!).
Psycho
Establishment
Beiträge: 156
Registriert: 16.09.2002, 14:23

Re: Welchen Namen hat diese Optimierung?

Beitrag von Psycho »

Wenn du die zu hookenden Funktionen tatsächlich über so eine Textdefinition dynamisch hooken willst wirste nicht drumherum kommen zur Laufzeit Code erzeugen zu müssen.
Die einfachste Lösung für mich wäre, einfach hundert Dummy-Funktionen mit HOOKED_FUNCTION(hookedFunction1) bis hookedFunction100 zu definieren und dann den gewünschten Hooks zuzuweisen. Das mit dem Compiler ist auch eine gute Idee, aber ich gehe einen anderen Weg. Plattformunabgänigkeit spielt für mich keine Rolle.
Es reicht bereits aus, zu jeder zu hookenden Funktion zu wissen, wieviele Parameter sie bekommt (in Bytes). Dann einfach die Parameter etwas weiter auf den Stack hochschieben, in den gewonnenen Freiraum die lokalen (zum Loggen notwendigen) Variablen plazieren, und beim Rücksprung hast du dann sowohl deine lokalen Variablen wie auch den Rückgabewert auf dem Stack liegen. Einfach noch loggen, die lokalen Variablen wieder vom Stack runterschmeißen und zurückspringen.
Ich weiß noch nicht genau, ob ich das so machen werde, den falls ja, muss für jeden Hook die komplette Parameterliste bekannt sein (die reine Bytezahl reicht imo nicht, denn ich will keine Werte wie 0x7C34567 loggen, sondern den dahinterliegenden String als Beispiel). Ich hatte jedoch vor, eine Option "hooke alles" einzubauen, die alle Funktionen im ImportTable hookt und dann ohne Parameter einfach loggt, welche Funktionen wann aufgerufen wurden. Ich werde vermutlich beide Varianten anbieten, da der Rückgabewert ja bei vielen Funktionen wichtig ist.
Helmut
Establishment
Beiträge: 237
Registriert: 11.07.2002, 15:49
Wohnort: Bonn
Kontaktdaten:

Re: Welchen Namen hat diese Optimierung?

Beitrag von Helmut »

Mit platformunabhängig wollte ich auf Amds 64bit Architektur anspielen, und die nimmt unter Windows langsam doch eine erhebliche Rolle ein, und bietet keinen Inline Assembler an.
Und um Assembler wirste bei der Makromethode nicht drumrumkommen, um die Parameter auszulesen. Viel Spaß wünsch ich da schonmal bei den ganzen Callingconventions, Parametertypgrößen und den Floatingpoint Registern ;) Die einfachste Lösung wäre das sicher nicht.

Ciao
Helmut
antisteo
Establishment
Beiträge: 854
Registriert: 15.10.2010, 09:26
Wohnort: Dresdem

Re: Welchen Namen hat diese Optimierung?

Beitrag von antisteo »

Psycho hat geschrieben:Aber kann ich die Optimierung auch gezielt abschalten? Ich möchte ja nicht auf alle Optimierungen verzichten.
Da C++ keine Linker-, Optimizer-, und Compilersteuerung im Quelltext erlaubt, nein.
Grundlegend gibt es das aber, nämlich in Pascal, wo man für eine Zeile mal schnell die Opimierung abschaltet, für den anderen Block Warnings deaktiviert und in der dritten Datei dem Linker einen zusätzlichen Parameter hinwirft.

In deinem konkreten Fall wäre wohl ein kleiner Umweg über "traditionelle" Verfahren nötig - ein zusätzlicher Parameter in die Funktion, damit sie weiß, wo sie vorher war.
http://fedoraproject.org/ <-- freies Betriebssystem
http://launix.de <-- kompetente Firma
In allen Posts ist das imo und das afaik inbegriffen.
Benutzeravatar
Schrompf
Moderator
Beiträge: 4864
Registriert: 25.02.2009, 23:44
Benutzertext: Lernt nur selten dazu
Echter Name: Thomas Ziegenhagen
Wohnort: Dresden
Kontaktdaten:

Re: Welchen Namen hat diese Optimierung?

Beitrag von Schrompf »

Das ist falsch, C++ unterstützt Optimierungssteuerungen für Code-Teile. Das sollte als Aussage reichen, um antisteos Unsinn ins rechte Licht zu rücken.

Antisteo, Du bist bereits bei Developia für Deine permanenten tendenziösen Falschaussagen rausgeflogen. Wenn Du etwas nicht weißt oder nur vermutest, dann sag das. Wenn Du aber weiterhin mit so plumper Stimmungsmache auftrittst, fliegst Du auch hier raus. Betrachte das als offizielle Warnung.
Früher mal Dreamworlds. Früher mal Open Asset Import Library. Heutzutage nur noch so rumwursteln.
Benutzeravatar
Krishty
Establishment
Beiträge: 8261
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: Welchen Namen hat diese Optimierung?

Beitrag von Krishty »

Falsch ist das doch garnicht -- C++ erlaubt es tatsächlich nicht. Es erlaubt nur Compiler-abhängige #pragmas, die bei VCpp zufällig die Möglichkeit bieten, bestimmte Optimierungen auf Funktionsebene ein- oder abzuschalten (und alles andere Pascal-mäßige auch). Und die Optimierung, die hier zur Debatte steht, gehört eben nicht dazu.

Psycho hat aber gewissermaßen selber schuld, weil sein Programm nicht standardkonform ist -- der Standard schreibt nirgends vor, dass unterschiedliche Funktionen unterschiedliche Adressen haben müssen und sich trotzdem darauf zu verlassen ist eine wackelige Sache.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
Schrompf
Moderator
Beiträge: 4864
Registriert: 25.02.2009, 23:44
Benutzertext: Lernt nur selten dazu
Echter Name: Thomas Ziegenhagen
Wohnort: Dresden
Kontaktdaten:

Re: Welchen Namen hat diese Optimierung?

Beitrag von Schrompf »

Jeder andere Compiler erlaubt das doch auch. Und das eine programmweite Optimierung, die im Linker stattfindet, nicht für ausgewählte Programmteile deaktivierbar ist, ist prinzipiell klar.
Früher mal Dreamworlds. Früher mal Open Asset Import Library. Heutzutage nur noch so rumwursteln.
Benutzeravatar
Krishty
Establishment
Beiträge: 8261
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: Welchen Namen hat diese Optimierung?

Beitrag von Krishty »

Richtig: es ist ein Compiler-Feature, kein Sprach-Feature. Ein Gros der anderen Compiler erlaubt es, aber jeder mit anderer Syntax und Funktionsweise. Auch sind die meisten programmübergreifenden Optimierungen des (VCpp-)Linkers tatsächlich für bestimmte Programmteile steuerbar. Nur gehört diese eine zur ausschließlich global steuerbaren Minderheit.

Wenn du ihn hier offiziell ankackst, dann bitte deswegen, weil sein Post nicht konstruktiv zur Problemlösung beigetragen hat (wobei auch das streitbar ist) ... aber nicht alles sofort als falsch abstempeln.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
eXile
Establishment
Beiträge: 1136
Registriert: 28.02.2009, 13:27

Re: Welchen Namen hat diese Optimierung?

Beitrag von eXile »

antisteo hat geschrieben:Ich weiß nicht, was du programmieren willst, aber es gibt sicherlich auch eine [weniger performante] "saubere" Lösung.
Naja, was er programmieren will, hat er ja schon erklärt. :) Eine saubere Lösung wird es nicht geben, da solche API-Hooking-Geschichten eindeutig die Sprachmittel von C übersteigt (und auch in C++ nichts dergleiches eingeführt wurde). Man kann in C nicht halbe Stackframes basteln, die man sich passend zusammenbaut. Übrigens manschen selbst die bei Microsoft mit ihren Microsoft Detours in der Assembler-Suppe rum ;)
Alexander Kornrumpf
Moderator
Beiträge: 2116
Registriert: 25.02.2009, 13:37

Re: Welchen Namen hat diese Optimierung?

Beitrag von Alexander Kornrumpf »

Moderator Action:

Ich habe versucht den Thread nach bestem Gewissen aufzutrennen. Leider überlappt sich Inhalt und Meta-Diskussion hier etwas.
Alles zur Verwarnung ab jetzt hier:

http://zfx.info/viewtopic.php?f=9&t=

http://zfx.info/viewtopic.php?f=9&t=1120&p=13043#p13043
Antworten