News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

echo procedure name

Started by korte, January 23, 2009, 04:00:27 PM

Previous topic - Next topic

korte



proc1 proc
   .echo procedure name
proc1 endp


how I can detect the name of the procedure (inside a procedure).
I want to echo


Jimg

I've often wanted such a function for tracing, but have never found a way, so I'm anxiously awaiting the answer also.

jj2007

Easy at runtime, see below, but apparently impossible from within a macro, due to the sequential nature of macro expansion. However, since you are the master of the code, why not replace

proc1 proc
   .echo procedure name
proc1 endp

with

proc1 proc
   .echo procedure proc1
proc1 endp


??

include \masm32\include\masm32rt.inc

WhereAmI MACRO
  tmp$ CATSTR <You are currently in Pro_>, %CurProcCt, <, named >, <cpn>
  % echo tmp$
ENDM

.code

start:
call Pro_2
call Pro_1
call Pro_3
call Pro_3
call Pro_3
; .err ; remove comment to see the echo tmp$
exit

Pro_1 proc
CurProcCt = 1
cpn equ A
WhereAmI
MsgBox 0, chr$(CurProcCt+48), "You are in Pro", MB_OK
ret
Pro_1 endp

Pro_2 proc
CurProcCt = 2
cpn equ B
WhereAmI
MsgBox 0, chr$(CurProcCt+48), "You are in Pro", MB_OK
ret
Pro_2 endp

Pro_3 proc
CurProcCt = 3
cpn equ C
WhereAmI
MsgBox 0, chr$(CurProcCt+48), "You are in Pro", MB_OK
ret
Pro_3 endp


end start

drizz

You must use custom prologue/epilogue macro to get proc name.
Jimg check out this attachment.


EDIT: I can't attach
An Error Has Occurred!
The upload folder is full. Please try a smaller file and/or contact an administrator.
The truth cannot be learned ... it can only be recognized.

drizz

posting it in CODE
;; prologue, epilogue, seh

pushcontext LISTING
.NOLIST
.NOCREF
.NOLISTMACRO

PEXCEPTION_RECORD TYPEDEF PTR EXCEPTION_RECORD
PCONTEXT TYPEDEF PTR CONTEXT
PNT_TIB TYPEDEF PTR NT_TIB

;; RETURN : EXCEPTION_DISPOSITION in EAX
EXCEPTION_ROUTINE TYPEDEF PROTO C \
ExceptionRecord:PEXCEPTION_RECORD,\
EstablisherFrame:PVOID,\
ContextRecord:PCONTEXT,\
DispatcherContext:PVOID
PEXCEPTION_ROUTINE TYPEDEF PTR EXCEPTION_ROUTINE

PEXCEPTION_REGISTRATION_RECORD TYPEDEF PTR EXCEPTION_REGISTRATION_RECORD
EXCEPTION_REGISTRATION_RECORD struct
Next PEXCEPTION_REGISTRATION_RECORD ?
Handler PEXCEPTION_ROUTINE ?
EXCEPTION_REGISTRATION_RECORD ends


; userparams: <FORCEFRAME>,<FORCENOFRAME>,<SEH>
assume fs:nothing


.data?
__current_seh_calee dd ?; single thread only!
__seh_save_ebp dd ?
__seh_save_esi dd ?
__seh_save_edi dd ?

.code

IFDEF DEBUG
GetExceptStr proc dwExceptCode
mov eax,dwExceptCode
.if eax == STATUS_BREAKPOINT
mov eax,T('BREAKPOINT')
.elseif eax == STATUS_SINGLE_STEP
mov eax,T('SINGLE_STEP')
.elseif eax == STATUS_GUARD_PAGE_VIOLATION
mov eax,T('GUARD_PAGE_VIOLATION')
.elseif eax == STATUS_ACCESS_VIOLATION
mov eax,T('ACCESS_VIOLATION')
.elseif eax == STATUS_ILLEGAL_INSTRUCTION
mov eax,T('ILLEGAL_INSTRUCTION')
.elseif eax == STATUS_PRIVILEGED_INSTRUCTION
mov eax,T('PRIVILEGED_INSTRUCTION')
.elseif eax == STATUS_INTEGER_DIVIDE_BY_ZERO
mov eax,T('INTEGER_DIVIDE_BY_ZERO')
.elseif eax == EXCEPTION_FLT_DIVIDE_BY_ZERO
mov eax,T('FLT_DIVIDE_BY_ZERO')
.else
mov edx,T('        ')
push edx
invoke wsprintf,edx,T('%.8X'),eax
pop eax
.endif
ret
GetExceptStr endp
ENDIF

IFDEF DEBUG
.data
db "Project build date: "
db @CatStr(<!">,@SubStr(%@Date,4,2),<.>,@SubStr(%@Date,1,2),<.>,@SubStr(%@Date,7,2),<!">),13,10
db "Masm v",@CatStr(<!">,@SubStr(@CatStr(<%@Version>),1,1),<.>,@SubStr(@CatStr(<%@Version>),2,2),<!">),0
sehExceptionCap db 'indolent programmer!',0
sehExceptionCp2 db 'EXCEPTION NON CONTINUABLE',0
sehExceptionMsg db 'Exception Occured at Address : %.8X',13,10
db 'Exception Code : %s',13,10,13,10
db 'Last Function Recorded was : %s',13,10
szcontb db 13,10
db 'Continue?',0
.data?
sehExceptionMsgbuff db 100h dup(?)
.code
ENDIF

__seh__UnhandledException proc
pushad
mov esi,[esp][4*8][1*4] ;; pExceptPtrs
mov edi,[esi].EXCEPTION_POINTERS.pExceptionRecord
mov esi,[esi].EXCEPTION_POINTERS.ContextRecord
invoke GetExceptStr,[edi].EXCEPTION_RECORD.ExceptionCode
mov edx,eax
mov eax,__dbg_lastprocname
.if !eax
mov eax,offset __dbg_1
.endif
mov szcontb,0
invoke wsprintf,addr sehExceptionMsgbuff,addr sehExceptionMsg,\
[edi].EXCEPTION_RECORD.ExceptionAddress,edx,eax
mov eax,MB_OK or MB_ICONHAND or MB_TOPMOST
mov edx,offset sehExceptionCp2
invoke MessageBox,0,addr sehExceptionMsgbuff,edx,eax
popad
mov eax,EXCEPTION_CONTINUE_SEARCH
retn
__seh__UnhandledException endp

__seh_handler proc ;c pExcept,pFrame,pContext,pDispatch
IFNDEF DEBUG
push edx
mov edx,[esp][3*4][4]; ContextRecord Arg of EXCEPTION_ROUTINE
mov eax,offset __cleanup_seh
mov [edx].CONTEXT.regEip,eax
mov eax,[__seh_save_ebp]
mov [edx].CONTEXT.regEbp,eax
mov eax,[__seh_save_edi]
mov [edx].CONTEXT.regEdi,eax
mov eax,[__seh_save_esi]
mov [edx].CONTEXT.regEsi,eax
or [edx].CONTEXT.regEax,-1
xor eax,eax ; ExceptionContinueExecution
pop edx
retn; CDECL
ELSE
pushad
mov edi,[esp][4*8][3*4] ;; Context
mov esi,[esp][4*8][1*4] ;; pExcept
push offset __cleanup_seh
pop [edi].CONTEXT.regEip
push [__seh_save_ebp]
pop [edi].CONTEXT.regEbp
push [__seh_save_edi]
pop [edi].CONTEXT.regEdi
push [__seh_save_esi]
pop [edi].CONTEXT.regEsi
mov ebx,[esi].EXCEPTION_RECORD.ExceptionFlags
invoke GetExceptStr,[esi].EXCEPTION_RECORD.ExceptionCode
mov edx,eax
mov eax,__dbg_lastprocname
.if !eax
mov eax,offset __dbg_1
.endif
.if ebx == EXCEPTION_NONCONTINUABLE
mov szcontb,0
.else
mov szcontb,13
.endif
invoke wsprintf,addr sehExceptionMsgbuff,addr sehExceptionMsg,\
[esi].EXCEPTION_RECORD.ExceptionAddress,edx,eax
mov eax,MB_YESNO or MB_ICONERROR or MB_TOPMOST
mov edx,offset sehExceptionCap
.if ebx == EXCEPTION_NONCONTINUABLE
mov eax,MB_OK or MB_ICONHAND or MB_TOPMOST
mov edx,offset sehExceptionCp2
.endif
invoke MessageBox,0,addr sehExceptionMsgbuff,edx,eax
or [edi].CONTEXT.regEax,-1
.if eax == IDNO || ebx == EXCEPTION_NONCONTINUABLE
mov eax,offset __seh_terminate
mov [edi].CONTEXT.regEip,eax
.endif
popad
xor eax,eax
retn
ENDIF
__seh_handler endp

__seh_terminate proc
xor eax,eax
mov edx,[_imp__ExitProcess@4]
dec eax
push eax
call edx
int 3
__seh_terminate endp

__setup_seh proc
mov __current_seh_calee,eax
pop eax
mov __seh_save_ebp,ebp
mov __seh_save_edi,edi
mov __seh_save_esi,esi
push offset __seh_handler
push fs:[NT_TIB.ExceptionList]
mov fs:[NT_TIB.ExceptionList],esp
push eax
retn
__setup_seh endp

__cleanup_seh proc
mov esp,fs:[NT_TIB.ExceptionList]
pop fs:[NT_TIB.ExceptionList]
add esp,4
push dword ptr [__current_seh_calee]
retn
__cleanup_seh endp

?Prolog MACRO procname, flags, parambytes, localbytes, reglist, userparams
LOCAL r,fforce,fseh
;%echo procname, flags, parambytes, localbytes, reglist, userparams
ifdef DEBUG
ifndef __dbg_lastprocname
.data
align 4
__dbg_lastprocname dd offset __dbg_1
__dbg_1 db '???',0
.code
endif
.data
__dbg_sz&procname db '&procname',0
.code
mov dword ptr [__dbg_lastprocname],offset __dbg_sz&procname
endif

fforce = 0
fseh = 0
for r,<userparams>
ifidni <&r>,<FORCEFRAME>
fforce = 1
elseifidni <&r>,<FORCENOFRAME>
fforce = 2
elseifidni <&r>,<SEH>
fseh = 1
endif
endm

IF (parambytes+localbytes) NE 0
if fforce ne 2
push ebp
mov ebp,esp
endif
IF localbytes NE 0
add esp,-localbytes
ENDIF
elseif fforce eq 1
push ebp
mov ebp,esp
ENDIF

IFNB <reglist>
FOR r, reglist
push r
ENDM
ENDIF

IF fseh eq 1
mov eax,offset __&procname&__cleanup
call __setup_seh
endif
EXITM %localbytes

ENDM

?Epilog MACRO procname, flags, parambytes, localbytes, reglist, userparams
LOCAL r,fforce,fseh
;;%echo procname, flags, parambytes, localbytes, reglist, userparams
fforce = 0
fseh = 0
for r,<userparams>
ifidni <&r>,<FORCEFRAME>
fforce = 1
elseifidni <&r>,<FORCENOFRAME>
fforce = 2
elseifidni <&r>,<SEH>
fseh = 1
endif
endm

IF fseh eq 1
call __cleanup_seh
__&procname&__cleanup:
endif

if (fforce eq 2) and (localbytes ne 0)
add esp,localbytes
endif

IFNB <reglist>
FOR r, reglist
pop r
ENDM
ENDIF

if fforce ne 2
IF (parambytes+localbytes NE 0) OR (fforce eq 1) 
leave
;mov esp,ebp
;pop ebp
ENDIF
endif

; flags and 10000b = true :: caller cleans stack
IF ( (flags and 10000b) ) OR ( parambytes EQ 0 )
ret
ELSE
ret parambytes
ENDIF

ENDM

popcontext LISTING


OPTION PROLOGUE:?Prolog
OPTION EPILOGUE:?Epilog
The truth cannot be learned ... it can only be recognized.

Jimg


Jimg

As it sits, I get:
Assembling: F:\WinAsm\Progs\alltemps\tst7\tst.asm
F:\WinAsm\Progs\alltemps\tst7\tst.asm(66) : error A2006: undefined symbol : T
F:\WinAsm\Progs\alltemps\tst7\tst.asm(66) : error A2114: INVOKE argument type mismatch : argument : 0
F:\WinAsm\Progs\alltemps\tst7\tst.asm(310) : error A2088: END directive required at end of file
F:\WinAsm\Progs\alltemps\tst7\tst.asm(48) : error A2006: undefined symbol : T
F:\WinAsm\Progs\alltemps\tst7\tst.asm(50) : error A2006: undefined symbol : T
F:\WinAsm\Progs\alltemps\tst7\tst.asm(52) : error A2006: undefined symbol : T
F:\WinAsm\Progs\alltemps\tst7\tst.asm(54) : error A2006: undefined symbol : T
F:\WinAsm\Progs\alltemps\tst7\tst.asm(56) : error A2006: undefined symbol : T
F:\WinAsm\Progs\alltemps\tst7\tst.asm(58) : error A2006: undefined symbol : T
F:\WinAsm\Progs\alltemps\tst7\tst.asm(60) : error A2006: undefined symbol : T
F:\WinAsm\Progs\alltemps\tst7\tst.asm(62) : error A2006: undefined symbol : T
F:\WinAsm\Progs\alltemps\tst7\tst.asm(64) : error A2006: undefined symbol : T
F:\WinAsm\Progs\alltemps\tst7\tst.asm(97) : error A2006: undefined symbol : __dbg_lastprocname
F:\WinAsm\Progs\alltemps\tst7\tst.asm(99) : error A2006: undefined symbol : __dbg_1
F:\WinAsm\Progs\alltemps\tst7\tst.asm(143) : error A2006: undefined symbol : __dbg_lastprocname
F:\WinAsm\Progs\alltemps\tst7\tst.asm(145) : error A2006: undefined symbol : __dbg_1
F:\WinAsm\Progs\alltemps\tst7\tst.asm(174) : error A2006: undefined symbol : _imp__ExitProcess@4



if I move the prolog macro up, no errors.  Now to test ......

drizz

It's very simple to use.

DEBUG EQU <nothing but evil>
.NOLIST
.NOCREF
.NOLISTMACRO
.686p
.mmx
.xmm
.model flat,stdcall
option casemap:none
assume fs:nothing
include windows.inc
include kernel32.inc
includelib kernel32.lib
include user32.inc
includelib user32.lib

T MACRO __qstr:VARARG
LOCAL __sym
.DATA
ALIGN 4
__sym DB __qstr,0
ALIGN 4
.CODE
EXITM <OFFSET __sym>
ENDM

.LIST
include catchexception.inc

TestProc proc <SEH>
xor eax,eax
mov eax,[eax]
ret
TestProc endp

start:
call TestProc
invoke ExitProcess
end start

The truth cannot be learned ... it can only be recognized.

Jimg

Okay, getting closer.  Down to-

F:\WinAsm\Progs\alltemps\tst7\catchexception.inc(305) : error A2008: syntax error : Report
F:\WinAsm\Progs\alltemps\tst7\tst.asm(40) : error A2137: too few arguments to INVOKE
F:\WinAsm\Progs\alltemps\tst7\catchexception.inc(169) : error A2006: undefined symbol : _imp__ExitProcess@4

I'll find it.

Jimg

Opps, mostly my fault.  cut and paste, ugh.

only error left-
F:\WinAsm\Progs\alltemps\tst7\catchexception.inc(169) : error A2006: undefined symbol : _imp__ExitProcess@4

drizz

ah yes, sry, my inlcude files look like this
EXTERNDEF STDCALL _imp__EnumTimeFormatsW@12:PPROTO@12
EXTERNDEF STDCALL _imp__EnumUILanguagesA@12:PPROTO@12
EXTERNDEF STDCALL _imp__EnumUILanguagesW@12:PPROTO@12
EXTERNDEF STDCALL _imp__EraseTape@12:PPROTO@12
EXTERNDEF STDCALL _imp__EscapeCommFunction@8:PPROTO@8
EXTERNDEF STDCALL _imp__ExitProcess@4:PPROTO@4
EXTERNDEF STDCALL _imp__ExitThread@4:PPROTO@4
EXTERNDEF STDCALL _imp__ExpandEnvironmentStringsA@12:PPROTO@12
EXTERNDEF STDCALL _imp__ExpandEnvironmentStringsW@12:PPROTO@12
EXTERNDEF STDCALL _imp__FatalAppExitA@8:PPROTO@8
No jmp thunk is generated

PROTO@4 TYPEDEF PROTO STDCALL :DWORD
EXTERNDEF STDCALL _imp__ExitProcess@4:PTR PROTO@4
;ExitProcess EQU <_imp__ExitProcess@4>

http://www.masm32.com/board/index.php?topic=6369.0

so: mov eax,[_imp__ExitProcess@4]
is equal to eax=getprocaddress(exitprocess) but the address is from import table
The truth cannot be learned ... it can only be recognized.

Jimg

It works. :U  Now to figure out how.

drizz

You mentioned you wanted it for tracing so i included the seh stuff too, it's my old code and it definitely needs to be rewritten.
The truth cannot be learned ... it can only be recognized.

Jimg

Yeah, the simple answer to the OP's question would be a prologue identical the the default PROLOGUEDEF, with the addition of setting an external variable to the procname parameter.

Any simple way to get a copy of PROLOGUEDEF?  It seems it could be quite complicated to duplicate from scratch taking into account the various proc types and such.

drizz

The truth cannot be learned ... it can only be recognized.