Herausfinden woher meine Procedure aufgerufen wird

Für allgemeine Fragen zur Programmierung mit PureBasic.
stevie1401
Beiträge: 659
Registriert: 19.10.2014 15:51
Kontaktdaten:

Herausfinden woher meine Procedure aufgerufen wird

Beitrag von stevie1401 »

Ich habe die Procedure MeineProc()


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

Ist das irgendwie machbar?
Ich programmiere nur noch mit Linux.
Linux Mint 21.x
Benutzeravatar
mk-soft
Beiträge: 3695
Registriert: 24.11.2004 13:12
Wohnort: Germany

Re: Herausfinden woher meine Procedure aufgerufen wird

Beitrag 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()

Alles ist möglich, fragt sich nur wie...
Projekte ThreadToGUI / EventDesigner V3 / OOP-BaseClass-Modul
Downloads auf MyWebspace / OneDrive
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8675
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 32 GB DDR4-3200
Ubuntu 22.04.3 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken
Kontaktdaten:

Re: Herausfinden woher meine Procedure aufgerufen wird

Beitrag 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.
Bild
Benutzeravatar
#NULL
Beiträge: 2235
Registriert: 20.04.2006 09:50

Re: Herausfinden woher meine Procedure aufgerufen wird

Beitrag 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, 
my pb stuff..
Bild..jedenfalls war das mal so.
stevie1401
Beiträge: 659
Registriert: 19.10.2014 15:51
Kontaktdaten:

Re: Herausfinden woher meine Procedure aufgerufen wird

Beitrag von stevie1401 »

Super!
Danke für eure Tips! :)
Ich programmiere nur noch mit Linux.
Linux Mint 21.x
Benutzeravatar
STARGÅTE
Kommando SG1
Beiträge: 6996
Registriert: 01.11.2005 13:34
Wohnort: Glienicke
Kontaktdaten:

Re: Herausfinden woher meine Procedure aufgerufen wird

Beitrag 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)
PB 6.01 ― Win 10, 21H2 ― Ryzen 9 3900X, 32 GB ― NVIDIA GeForce RTX 3080 ― Vivaldi 6.0 ― www.unionbytes.de
Aktuelles Projekt: Lizard - Skriptsprache für symbolische Berechnungen und mehr
Benutzeravatar
juergenkulow
Beiträge: 188
Registriert: 22.12.2016 12:49
Wohnort: :D_üsseldorf-Wersten

Re: Herausfinden woher meine Procedure aufgerufen wird

Beitrag 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)
Bitte stelle Deine Fragen, denn den Erkenntnisapparat einschalten entscheidet über das einzig bekannte Leben im Universum.

Jürgen Kulow Wersten :D_üsseldorf NRW D Europa Erde Sonnensystem Lokale_Flocke Lokale_Blase Orion-Arm
Milchstraße Lokale_Gruppe Virgo-Superhaufen Laniakea Sichtbares_Universum
Benutzeravatar
STARGÅTE
Kommando SG1
Beiträge: 6996
Registriert: 01.11.2005 13:34
Wohnort: Glienicke
Kontaktdaten:

Re: Herausfinden woher meine Procedure aufgerufen wird

Beitrag von STARGÅTE »

Darüber habe ich noch nicht nachgedacht, aber wie mache ich dann weiter wenn ich diese Adresse kenne?
PB 6.01 ― Win 10, 21H2 ― Ryzen 9 3900X, 32 GB ― NVIDIA GeForce RTX 3080 ― Vivaldi 6.0 ― www.unionbytes.de
Aktuelles Projekt: Lizard - Skriptsprache für symbolische Berechnungen und mehr
Benutzeravatar
Mijikai
Beiträge: 754
Registriert: 25.09.2016 01:42

Re: Herausfinden woher meine Procedure aufgerufen wird

Beitrag 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.
Benutzeravatar
#NULL
Beiträge: 2235
Registriert: 20.04.2006 09:50

Re: Herausfinden woher meine Procedure aufgerufen wird

Beitrag 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.
Zuletzt geändert von #NULL am 13.01.2021 13:05, insgesamt 1-mal geändert.
my pb stuff..
Bild..jedenfalls war das mal so.
Antworten