Can someone give me some advices of how to do the following:
I wrote small tracer tool, which should works like a snoopy, but only on given binary (not on everything). So far using SetMethod() i patch the function of library i need to trace, and now i need in the patched function compare things, and printf only when call to this function is happens to be from my binary of choose.
Currently, i thinking like provide the name (or a full path?) of a binary to the tracer tool on the running, and then in patched function, somehow compare if call was from that binary or not. How better to handle it all ? The name of process is no go, as it will be just “shell process” or so.. Giving "just" binary name imho also no go, as there can be many with same name. Then just full path to the binary ?
I dont need stack trace, by trace i mean ability to catch call to some function of library , when called from given binary. Like snoopy, but not all of them from all processes
I mean tracer is standalone tool, and binary to trace too. I cant findtask == mybinarytask, because trace tool dont know what mybinarytask are: i need to find it from name of binary and probably given path. I.e. how i can know for sure from tracer the mybinarytask, if i only provide name and maybe path to binary to trace ? Did return by findtask give a name of binary and a full path to ?
Ok thanks to Andrea find out a way to get name of binary from the findtask(), but now have some issue : i do patch CallHookPkt(), and instert there that:
Because cli_CommandName is BPTR, i had to do this conversion and buffer copy (to be able later to compare with argv[1] name).
So, CallHookPkt uses everywhere and there a lot of it, but once i have by string with CopyStrinBSTRToC(), then after a second i simple crashes in dopusclock_hook() which seems to use a lot of CallHookPkt()s.
Question is why ? I can't call CopyStringBSTRToC in such a patched function ? Or it should be done differently ? All i need is to compare argv[1] with the ComandName, and if it equal, then, and only then, do my stuff, in other ways keep back to original.
@LiveForIt Thanks ! That it ! Through i had to add also check on cli->cli_Module too, to be sure that this is Cli command loaded, and not something like Workbench process.
Now, do we have only processes and tasks in the system which may use CallHookPkt() ?
I want now not only check what exactly MY binary do, but i also want to count every CallHookPkt() calls from every task/process/etc on the system.
I.e. i want to count, how many CallHookPkt() calls happens in all the task/proccess/whatever_else in the fully loaded system per 1 second.
So far i think to do it like this:
1. That code to check process. Count what process how many times calls the CallHookPkt(), and print out time and amount on exit.
2. if not process , then it is a task (right ?), so then we do in opposite:
@kas1e It doesn't make any difference if you use struct Process or struct Task when using
if (IS_PROCESS(process))
The fist part of struct Process is struct Task and as long as you only access the struct Task parts there is no problem. Only access struct Process parts after you have checked that it's a DOS Process and not an Exec Task.
If you don't want to use macros and struct Process you can use something like
if (NT_PROCESS == process->pr_Task.tc_Node.ln_Type)
So.. if interrupts are also the category which can call CallHookPkt(), how can i trace them too ? My main goal is just to do that:
1). Absolute count of all CallHookPkt() in the loaded system: that easy, just count + printf.
2). Count per second all the processes and whatever else (interrupts?) and on exit out name of the tasm/process/etc, the time is spend and amount of CallHookPkt calls.
Just want theoretically know, how many of them, and co.
For now count how many CallHookPkt's happens in the system when we do nothing , but have loaded up ONLY plain WB (no amidock, nothing else) : 50 per second. This is "Workbench" and "dos_signal_server".
If i fire-up amidock with all my realtime dokies, then amount of CallHookPkt calls is start to be about ~250 calls per second in summary with system's ones!
Btw, is there any possible way , to trace, what function from given process/task call the CallHookPkt() ? I mean, not the application's one, but the library's one it uses. I.e. i want to trace let's say some code where developer create asl.library's hook to filter screenmodes via ASL_Hook, and then, this one in the ASL itself do use CallHookPkt() : but i want to know from which library's function this CallHookPkt() call is to come (taking into account that i do not know that it is come from asl.library, as i only see the call to patched CallHookPkt).
Should i probabaly take all system libraryes, find out all functions providing hooking functionality, and trace them as well ?
@kas1e I would have expected much more calls/s. layers and graphics (for example the BackFill Hooks), intuition (incl. all BOOPSI gadgets, images and data types, Windows alpha/shape/scrolling/etc., ...), IIRC Dockies (AmiDock) as well, and a lot more in AmigaOS uses Hooks.
So it did count all counts to CallHookPkt() and i see none of them coming from anything else than Dos_server and Workbnech.
But ! It can be very well, that most libraries do not use CallHookPkt() directly, but instead, self-made CallHook() from amiga.lib (or so), meaning that it still provide hooking functionality, but not via CallHookPkt() ?
@Joerg But again, we can see only name of process/task, but we can't see from which else it come too. I mean, Workbench can use asl, layers, etc. But in log we will see just "Workbench" task
I think many libs use CallHook() from amiga.lib, instead of "modern" CallHookPkt() which were created later ? At least intuition for sure (at least on old os3)
But ! It can be very well, that most libraries do not use CallHookPkt() directly, but instead, self-made CallHook() from amiga.lib (or so), meaning that it still provide hooking functionality, but not via CallHookPkt() ?
Should only be the case if you are using AmigaOS <= 3.x/m68k software, or AmigaOS 4.x ports which weren't fixed. Although CallHookPkt() is an AmigaOS 2.0 function a lot of AmigaOS <= 3.9 software didn't use it but called the h_entry function directly, or used an obsolte libamiga.a function (for Kickstart 1.x compatibility) doing that instead.
From the utility.library/CallHookPkt AutoDoc:
This form of transparency comes at a price: h_Entry must not be jumped
to directly, as calling 68k legacy code from native code will result in
a crash, and calling native code from 68k legacy code will result in
native code being interpreted as 68k code, with completely unpredictable
results.
@Joerg Then what it all mean is that : When we have "workbench" name in the task/process name with its 500 counts of CallHookPkt() - we do have only name of process from which this all happens, but not directly : i.e. we don' see there that workbench do call layers.library, or graphics.library, we only see that some process were involved in calling CallHookPkt(). But how can be detect _what_ exactly call it ? I.e. not the process from which we invoke it originally, but what call the CallHookPkt under the hood ?
Of course probably the best way will be to use GDB or db101/spotless, and instruction by instruction find out how the way from user application till final CallHookPkt() passed , but maybe it possible to trace without debugger and in more automatic way ?
@LiveForIt Quote:
Hook can be simple function pointer, does need to be a utility.library hook.
But then it's not a casual utility-like hook, but a self-made one, the ones we didn't count there. And IMHO most of amigaos4 libs do use CallHookPkt (at least even in old os3 times, ASL library already used CallHookPkt, and even string.gadget too)
Of course probably the best way will be to use GDB or db101/spotless, and instruction by instruction find out how the way from user application till final CallHookPkt() passed , but maybe it possible to trace without debugger and in more automatic way ?
You have to implement a stack backtrace in your IUtility->CallHookPkt() patch using IDebug->StackTrace() (problem: It's using a hook as well and you have to exclude this hook in your patch, otherwise you'll get an endless loop and crashes), IDebug->ObtainDebugSymbol(), etc., just like the debuggers do.