@kas1e
So if I understand correctly, ObtainDebugSymbol() assumed it was always being called from an exception context, and so always adjusted the address it was given. When called from a normal task context the adjustment is not required, and when it made the adjustment anyway, the address ended up being incorrect. (At least that's the effect, if not the actual problem.) Interesting.
To confirm this, I added a harmless DSI (a read from address zero) to my earlier example program. When the program "crashes" I can use Grim Reaper to display a stack trace, and indeed the source file name and line number are present. (The DSI can be ignored and the example program will terminate normally.)
And as you suggested, compensating for the bug by adding four to the address given to ObtainDebugSymbol() allows the source file name and line number to appear, confirming a workaround.
For those following along, here's the updated example program. By adding and removing comments you can demonstrate the bug or confirm the workaround. You can also remove a comment to trigger the DSI. Use the makefile from my earlier post (#26) to build the program.
// Simple example to demonstrate lack of source file name and line
// number in symbol information returned by ObtainDebugSymbol().
#include <exec/types.h>
#include <exec/debug.h>
#include <stdio.h>
#include <proto/exec.h>
int main(int argc, char **argv)
{
struct DebugSymbol *Ourself;
UNUSED uint32 Dummy;
// Get symbol information about ourself. Source file name and line
// number will not be displayed.
// Ourself = IDebug->ObtainDebugSymbol(&main, NULL);
// Get symbol information about ourself, with address adjusted to
// account for Exec bug. Source file name and line number will be
// displayed.
Ourself = IDebug->ObtainDebugSymbol(&main + 4, NULL);
// Display the base name.
if(Ourself && Ourself->SourceBaseName)
printf("Base name: %s\n", Ourself->SourceBaseName);
else
printf("No base name!\n");
// Display the function name.
if(Ourself && Ourself->SourceFunctionName)
printf("Function name: %s\n", Ourself->SourceFunctionName);
else
printf("No function name!\n");
// Display the source file name.
if(Ourself && Ourself->SourceFileName)
printf("Source file name: %s\n", Ourself->SourceFileName);
else
printf("No source file name!\n");
// Display the source file line number.
if(Ourself && Ourself->SourceLineNumber)
printf("Source line number: %ld\n", Ourself->SourceLineNumber);
else
printf("No source line number!\n");
// We're done with the symbol info.
IDebug->ReleaseDebugSymbol(Ourself);
// Uncomment to cause a harmless DSI. Source file name and line number
// will be displayed in stack trace.
// Dummy = *(uint32 *)0;
// All done.
return(0);
}
I modified Profyler to adjust the function address before passing it to ObtainDebugSymbol(), and confirmed that the source file name and line number now appear for programs being profiled. Nice!
Of course, once the new version of Exec comes out the workaround needs to be removed. If I wanted to test the version of Exec and only apply the workaround to versions prior to the fix, what version of Exec might I want to check for?