Seite 1 von 2

Herausfinden woher meine Procedure aufgerufen wird

Verfasst: 11.01.2021 12:51
von stevie1401
Ich habe die Procedure MeineProc()


Wie kann ich debuggen welche Procedure MeineProc im laufenden Betrieb aufruft?

Ist das irgendwie machbar?

Re: Herausfinden woher meine Procedure aufgerufen wird

Verfasst: 11.01.2021 13:41
von mk-soft

Code: Alles auswählen


Procedure MyFunction(Parent.s = "")
  
  If Parent
    Debug "Calling from " + Parent
  Else
    Debug "Calling from MainScope"
  EndIf
  
EndProcedure

Procedure Prog1()
  
  MyFunction(#PB_Compiler_Procedure)
  
EndProcedure

Procedure Prog2()
  
  MyFunction(#PB_Compiler_Procedure)
  
EndProcedure

Prog1()
Prog2()
MyFunction()


Re: Herausfinden woher meine Procedure aufgerufen wird

Verfasst: 11.01.2021 13:51
von NicTheQuick
Du kannst an der Stelle, an der du das wissen möchtest, einfach "CallDebugger" schreiben um dein Programm dort zu pausieren. Und dann gehst du im Menü "Debugger" auf "Aufrufverfolgung". Dort siehst du den kompletten Weg bis zu der Procedure, in der gerade pausiert wurde und du kannst zurückverfolgen wie es dazu kam.

Re: Herausfinden woher meine Procedure aufgerufen wird

Verfasst: 11.01.2021 15:43
von #NULL
Ergänzend zum Beipsiel von mk-soft: Wenn du nicht alle Stellen der Aufrufe ändern willst, kannst du auch deine Procedure umbenennen und ein Macro mit dem urspünglichen Namen zwischenschalten, das dir die Aufruf-Informationen automatisch übergibt.

Code: Alles auswählen

Procedure myProc_(param1, param2, callerInfo.s)
  Debug callerInfo
EndProcedure

Macro myProc(p1, p2)
  myProc_(p1, p2, #PB_Compiler_Filename + ", " + #PB_Compiler_Line + ", " + #PB_Compiler_Procedure)
EndMacro

; ----------------------

Procedure otherProc()
  myProc(11, 22)
EndProcedure

myProc(11, 22)
otherProc()
myProc(11, 22)

; ----------------------
; output:
; 
; PB_EditorOutput.pb, 16, 
; PB_EditorOutput.pb, 13, otherProc
; PB_EditorOutput.pb, 18, 

Re: Herausfinden woher meine Procedure aufgerufen wird

Verfasst: 11.01.2021 20:43
von stevie1401
Super!
Danke für eure Tips! :)

Re: Herausfinden woher meine Procedure aufgerufen wird

Verfasst: 11.01.2021 21:43
von STARGÅTE
Wo wir gerade bei diesem Thema sind.

Ich vermisse in PureBasic eine Art Back-tracing von Prozeduraufrufen. Zwar gibts es die Aufruftsverfolgung der IDE, aber ich habe halt im Programm keinen Zugriff darauf.
Hintergrund ist: Wenn ich ein Modul schreibe mit einer Fehlerausgabe àla DebuggerError oder DebuggerWarning, dann nützt es mit (bzw. dem Nutzer des Moduls) herzlich wenig, wenn er an die Stelle in der Prozedur im Modul selbst geleitet wird, wo man DebuggerError aufruft. Stattdessen möchte man die Zeile ein Level drüber markiert haben, wo die Modul-Prozedur aufgerufen wurde (die den Fehler ausgibt).

Alles mit Hilfs-Macros zu zupflastern kann ja nicht sinn der Sache sein
und DebuggerWarning würde immer noch an der "tiefsten Stelle" aufblinken.
Gibt es da echt keine andere Möglichkeit?

Meine Idee war damals folgende, welche die Aufrufsreihenfolge ausnutzt:
Ein Krampft ist es trotzdem.

Code: Alles auswählen

Global DebuggerErrorText.s
Procedure DebuggerErrorText(Text.s)
	DebuggerErrorText = Text
EndProcedure
Procedure.f DebuggerReturnFloat(Void.i, Function.f)
	ProcedureReturn Function
EndProcedure



CompilerIf #PB_Compiler_Debugger
Procedure.f CustomRoundFunction(Value.f, Round.f)
CompilerElse
Procedure.f CustomRound(Value.f, Round.f)
CompilerEndIf
	
	CompilerIf #PB_Compiler_Debugger
		If Round <= 0.0
			DebuggerErrorText("Round must be greater than 0.0")
			ProcedureReturn 0.0
		EndIf
	CompilerEndIf
	
	ProcedureReturn Round(Value/Round, #PB_Round_Nearest)*Round
	
EndProcedure

CompilerIf #PB_Compiler_Debugger
	Macro CustomRound(Parameter1, Parameter2)
		DebuggerReturnFloat(Bool(DebuggerErrorText="" Or DebuggerWarning(DebuggerErrorText)), CustomRoundFunction(Parameter1, Parameter2))
	EndMacro
CompilerEndIf

;- Example

Debug CustomRound(1.23, 0.25)

Debug CustomRound(12.3, 10)

Debug CustomRound(123, 0)

Re: Herausfinden woher meine Procedure aufgerufen wird

Verfasst: 12.01.2021 07:48
von juergenkulow
Hallo STARGÅTE,

hast Du mal darüber nachgedacht ob man das RSP Register auslesen könnte und im auf den Stack nach den Rücksprungadressen sucht. (+$58)

Re: Herausfinden woher meine Procedure aufgerufen wird

Verfasst: 12.01.2021 21:56
von STARGÅTE
Darüber habe ich noch nicht nachgedacht, aber wie mache ich dann weiter wenn ich diese Adresse kenne?

Re: Herausfinden woher meine Procedure aufgerufen wird

Verfasst: 12.01.2021 22:07
von Mijikai
So bekommt man die Rücksprung-Addresse:

Code: Alles auswählen

EnableExplicit

;x64 GET RETURN ADDRESS
;CHECK WITH EXTERNAL DEBUGGER!

Procedure.i Proc1(a.i,b.i)
  Protected ret.i
  !mov rax,[rsp + 0x38]
  !mov [p.v_ret],rax
  PrintN("RETURN1: 0x" + Hex(ret))
  ProcedureReturn
EndProcedure

Procedure.i Proc2(a.i,b.i,c.i,d.i,e.i,f.i,g.i,h.i)
  Protected ret.i
  !mov rax,[rsp + 0x38]
  !mov [p.v_ret],rax
  PrintN("RETURN2: 0x" + Hex(ret))
  ProcedureReturn
EndProcedure

Procedure.i Main()
  Proc1(1,2)
  Proc2(1,2,3,4,5,6,7,8)
  PrintN("MAIN: 0x" + Hex(@Main()))
  PrintN("PROC1: 0x" + Hex(@Proc1()))
  PrintN("PROC2: 0x" + Hex(@Proc2()))
  ProcedureReturn
EndProcedure

If OpenConsole(#Null$)
  Main()
  Input()
  CloseConsole()
EndIf

End
Jetzt könnte man zb. prüfen ob die Addresse innerhalb einer bestimmten Funktion liegt.
Oder die Opcodes rückwärts durchlaufen.

Re: Herausfinden woher meine Procedure aufgerufen wird

Verfasst: 13.01.2021 13:00
von #NULL
STARGÅTE hat geschrieben:Alles mit Hilfs-Macros zu zupflastern kann ja nicht sinn der Sache sein
[...]
Gibt es da echt keine andere Möglichkeit?
Ich denke nicht. Da die Debbugger-Commands sich dort melden, wo man sie im Code stehen hat, muss man sie halt irgendwie in die User-Code-Ebene bringen, und das geht halt nur mit Makros.
STARGÅTE hat geschrieben:und DebuggerWarning würde immer noch an der "tiefsten Stelle" aufblinken.
Wie meinst du das? Bei mir werden DebbuggerWarning/Error dort angezeigt, wo das Makro aufgelöst wurde, also im User-Code, und nicht etwa im Macro-Body oder dergleichen.