home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 6 / AACD06.ISO / AACD / Programming / ProfilePPC / ProfilePPC.c < prev    next >
C/C++ Source or Header  |  2000-01-09  |  12KB  |  409 lines

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <stdarg.h>
  5.  
  6. #include <exec/exec.h>
  7. #include <dos/dos.h>
  8. #include <dos/dosextens.h>
  9. #include <dos/dostags.h>
  10. #include <graphics/gfx.h>
  11. #include <proto/exec.h>
  12. #include <proto/dos.h>
  13. #include <proto/graphics.h>
  14.  
  15. #include <PowerUP/PPCLib/Interface.h>
  16. #include <PowerUP/PPCLib/tasks.h>
  17. #include <PowerUP/PPCLib/ppc.h>
  18. #include <PowerUP/PPCLib/object.h>
  19. #include <PowerUP/clib/ppc_protos.h>
  20. #include <PowerUP/pragmas/ppc_pragmas.h>
  21.  
  22. struct symbol_node {
  23.   struct symbol_node *left;
  24.   struct symbol_node *right;
  25.   ULONG addr;
  26.   ULONG size;
  27.   char *name;
  28.   ULONG count;
  29. };
  30.  
  31. struct StartupData
  32. {
  33.   void *M68kPort;  /* the PowerPC task can send messages to this port */
  34.   BPTR std_in;     /* standard input handle */
  35.   BPTR std_out;    /* standard output handle */
  36.   BPTR std_err;    /* standard error handle */
  37.   LONG ReturnCode; /* here we will find the return code from the PPC task */
  38.   ULONG Flags;     /* additional flags (currently unused) */
  39. };
  40.  
  41. #define STARTUPF_ELFLOADSEG    0x1
  42. #define MSGID_EXIT 0x44584954
  43.  
  44. struct Library *PPCLibBase = NULL;
  45. static void *object = NULL;
  46. static struct Hook scan_symbol_hook, exception_hook;
  47. static struct symbol_node *symbol_root = NULL;
  48. static struct Task *m68ktask;
  49. static void *M68kPort = NULL;
  50. static void *startup_msg = NULL;
  51. static struct StartupData *startup_data = NULL;
  52. static BOOL task_is_finished = FALSE;
  53. static ULONG pc = 0;
  54.  
  55. static char *StateString[] = {
  56.   "Invalid",
  57.   "Added  ",
  58.   "Run    ",
  59.   "Ready  ",
  60.   "Wait   ",
  61.   "-------",
  62.   "Removed"
  63. };
  64.  
  65. /**********************************************************************/
  66. void fatal (char *error, ...)
  67. {
  68.   va_list argptr;
  69.  
  70.   fprintf (stderr, "Fatal error: ");
  71.   va_start (argptr,error);
  72.   vfprintf (stderr, error, argptr);
  73.   va_end (argptr);
  74.   fprintf (stderr, "\n");
  75.  
  76.   exit (20);
  77. }
  78.  
  79. /****************************************************************************/
  80. static struct symbol_node *insert_info (struct symbol_node **p,
  81.                                         struct PPCObjectInfo *info)
  82. {
  83.   if (*p == NULL) {
  84.     if ((*p = (struct symbol_node *)malloc (sizeof(struct symbol_node))) == NULL)
  85.       fatal ("Out of memory!\n");
  86.     (*p)->left = NULL;
  87.     (*p)->right = NULL;
  88.     (*p)->addr = info->Address;
  89.     (*p)->size = info->Size;
  90.     if (((*p)->name = (char *)malloc(strlen(info->Name) + 1)) == NULL)
  91.       fatal ("Out of memory!\n");
  92.     strcpy ((*p)->name, info->Name);
  93.     (*p)->count = 0;
  94.     return (*p);
  95.   } else {
  96.     if (info->Address < (*p)->addr)
  97.       return (insert_info (&(*p)->left, info));
  98.     else if (info->Address > (*p)->addr)
  99.       return (insert_info (&(*p)->right, info));
  100.     else {
  101. //      printf ("%s and %s are coincident at %08x, sizes %d and %d\n",
  102. //              (*p)->name, info->Name, (*p)->addr, (*p)->size, info->Size);
  103.       if ((*p)->size < info->Size)
  104.         (*p)->size = info->Size;
  105.       return (*p);
  106.     }
  107.   }
  108. }
  109.  
  110. /****************************************************************************/
  111. static void fill_gaps (struct symbol_node *p)
  112. {
  113.   static struct symbol_node *prev_node = NULL;
  114.   static struct PPCObjectInfo info;
  115.   static char name[1024];
  116.  
  117.   if (p != NULL) {
  118.     fill_gaps (p->left);
  119.     if (prev_node != NULL) {
  120.       if (prev_node->addr + prev_node->size < p->addr) {
  121.         sprintf (name, "between %s and %s", prev_node->name, p->name);
  122.         info.Name = name;
  123.         info.Address = prev_node->addr + prev_node->size;
  124.         info.Size = p->addr - info.Address;
  125.         insert_info (&symbol_root, &info);
  126.       } else if (prev_node->addr + prev_node->size > p->addr) {
  127.         printf ("%s and %s overlap\n", prev_node->name, p->name);
  128.         prev_node->size = p->addr - prev_node->addr;
  129.       }
  130.     }
  131.     prev_node = p;
  132.     fill_gaps (p->right);
  133.   }
  134. }
  135.  
  136. /****************************************************************************/
  137. static struct symbol_node *lookup_info (struct symbol_node *p, ULONG addr)
  138. {
  139.   if (p == NULL)
  140.     return NULL;
  141.   else if (addr >= p->addr && addr < p->addr + p->size)
  142.     return p;
  143.   else if (addr < p->addr)
  144.     return (lookup_info (p->left, addr));
  145.   else
  146.     return (lookup_info (p->right, addr));
  147. }
  148.  
  149. /****************************************************************************/
  150. static void print_tree (struct symbol_node *p)
  151. {
  152.   if (p != NULL) {
  153.     print_tree (p->left);
  154.     if (p->count > 0)
  155.       printf ("0x%08lx\t0x%08lx\t%d\t%s\n", p->addr, p->size, p->count, p->name);
  156.     print_tree (p->right);
  157.   }
  158. }
  159.  
  160. /****************************************************************************/
  161. static void free_tree (struct symbol_node *p)
  162. {
  163.   if (p != NULL) {
  164.     free_tree (p->left);
  165.     free_tree (p->right);
  166.     if (p->name != NULL)
  167.       free (p->name);
  168.     free ((char *)p);
  169.   }
  170. }
  171.  
  172. /****************************************************************************/
  173. BOOL __asm __saveds ExceptionHookFunc (register __a0 struct Hook *exception_hook,
  174.                                        register __a2 void *task,
  175.                                        register __a1 struct ExceptionMsg *msg)
  176. {
  177.   if (msg->Type & EXCEPTION_MSG) {
  178.     if (msg->Type == EXCEPTION_FINISHTASK)
  179.       task_is_finished = TRUE;
  180.     else if (msg->Type == EXCEPTION_STOPTASK) {
  181.       pc = msg->SRR0;
  182.       Signal (m68ktask, SIGBREAKF_CTRL_F);
  183.     }
  184.     return TRUE;
  185.   }
  186.   return FALSE;
  187. }
  188.  
  189. /**********************************************************************/
  190. static void __asm __saveds ScanHookFunc (register __a0 struct Hook *exception_hook,
  191.                                          register __a2 void *elf_struct,
  192.                                          register __a1 struct PPCObjectInfo *info)
  193. {
  194.   if (info->Address != 0 && info->Size != 0 && strlen(info->Name) != 0)
  195.     insert_info (&symbol_root, info);
  196. //  printf ("0x%08lx\t0x%08lx\t%s\n", info->Address, info->Size,
  197. //          info->Name);
  198. }
  199.  
  200. /**********************************************************************/
  201. void _STD_cleanup (void)
  202. {
  203.   if (startup_data != NULL) {
  204.     PPCFreeVec (startup_data);
  205.     startup_data = NULL;
  206.   }
  207.   if (startup_msg != NULL) {
  208.     PPCDeleteMessage (startup_msg);
  209.     startup_msg = NULL;
  210.   }
  211.   if (M68kPort != NULL) {
  212.     PPCDeletePort (M68kPort);
  213.     M68kPort = NULL;
  214.   }
  215.   free_tree (symbol_root);
  216.   if (object != NULL) {
  217.     PPCUnLoadObject (object);
  218.     object = NULL;
  219.   }
  220.   if (PPCLibBase != NULL) {
  221.     CloseLibrary (PPCLibBase);
  222.     PPCLibBase = NULL;
  223.   }
  224. }
  225.  
  226. /**********************************************************************/
  227. int main (int argc, char *argv[])
  228. {
  229.   struct TagItem tags[22];
  230.   struct PPCObjectInfo info;
  231.   struct symbol_node *node;
  232.   BOOL ctrl_c_check;
  233.   int count, out_of_range_count, state_count[7], other_state_count, i;
  234.   ULONG Result, sig, state;
  235.   void *ppctask;
  236.   char *name;
  237.   static char args[1024];
  238.  
  239.   if (argc < 2) {
  240.     printf ("Usage: ProfilePPC <elf-prog> <args>...\n");
  241.     exit (10);
  242.   }
  243.  
  244.   m68ktask = FindTask (NULL);
  245.  
  246.   if ((PPCLibBase = OpenLibrary ("ppc.library", 0)) == NULL)
  247.     fatal ("Can't open ppc.library");
  248.  
  249.   if ((object = PPCLoadObject (argv[1])) == NULL)
  250.     fatal ("Can't load ELF object %s", argv[1]);
  251.  
  252.   scan_symbol_hook.h_Entry = (ULONG (*)(void)) ScanHookFunc;
  253.   scan_symbol_hook.h_SubEntry = (ULONG (*)(void)) NULL;
  254.   scan_symbol_hook.h_Data = (APTR) PPCLibBase;
  255.  
  256.   tags[0].ti_Tag = PPCELFINFOTAG_SCANSYMBOLHOOK;
  257.   tags[0].ti_Data = (ULONG) &scan_symbol_hook;
  258.   tags[1].ti_Tag = TAG_END;
  259.   Result = PPCGetObjectAttrs (NULL /*object*/, &info, tags);
  260.   printf ("PPCGetObjectAttrs Result = %d\n", Result);
  261.  
  262.   fill_gaps (symbol_root);
  263.  
  264.   info.Address = NULL;
  265.   info.Name = "_ixbaseobj";
  266.   tags[0].ti_Tag = TAG_END;
  267.   if (PPCGetObjectAttrs (object, &info, tags))
  268.     ctrl_c_check = FALSE;
  269.   else
  270.     ctrl_c_check = TRUE;
  271.  
  272.   tags[0].ti_Tag = TAG_END;
  273.   if ((M68kPort = PPCCreatePort (tags)) == NULL)
  274.     fatal ("PPCCreatePortTags() failed");
  275.  
  276.   if ((startup_msg = PPCCreateMessage (M68kPort, sizeof(struct StartupData)))
  277.                                                                         == NULL)
  278.     fatal ("PPCCreateMessage() failed");
  279.  
  280.   if ((startup_data = (struct StartupData *)PPCAllocVec (
  281.                         sizeof(struct StartupData), MEMF_CLEAR | MEMF_PUBLIC))
  282.                                                                         == NULL)
  283.     fatal ("PPCAllocVec() failed");
  284.  
  285.   args[0] = '\0';
  286.   for (i = 1; i < argc; i++) {
  287.     strcat (args, " ");
  288.     strcat (args, argv[i]);
  289.   }
  290.   startup_data->M68kPort = M68kPort;
  291.   startup_data->std_in = Input ();
  292.   startup_data->std_out = Output ();
  293.   startup_data->std_err = ((struct Process *)m68ktask)->pr_CES;
  294.   startup_data->Flags = STARTUPF_ELFLOADSEG;
  295.  
  296.   exception_hook.h_Entry = (ULONG (*)(void))ExceptionHookFunc;
  297.   exception_hook.h_SubEntry = (ULONG (*)(void))NULL;
  298.   exception_hook.h_Data = (APTR)PPCLibBase;
  299.  
  300.   tags[0].ti_Tag = PPCTASKTAG_WAITFINISH;
  301.   tags[0].ti_Data = FALSE;
  302.   tags[1].ti_Tag = PPCTASKTAG_INPUTHANDLE;
  303.   tags[1].ti_Data = (ULONG) Input ();
  304.   tags[2].ti_Tag = PPCTASKTAG_OUTPUTHANDLE;
  305.   tags[2].ti_Data = (ULONG) Output ();
  306.   tags[3].ti_Tag = NP_CloseInput;
  307.   tags[3].ti_Data = FALSE;
  308.   tags[4].ti_Tag = NP_CloseOutput;
  309.   tags[4].ti_Data = FALSE;
  310.   tags[5].ti_Tag = NP_Cli;
  311.   tags[5].ti_Data = TRUE;
  312.   tags[6].ti_Tag = PPCTASKTAG_BREAKSIGNAL;
  313.   tags[6].ti_Data = ctrl_c_check;
  314.   tags[7].ti_Tag = PPCTASKTAG_ARG1;
  315.   tags[7].ti_Data = (ULONG)args;
  316.   tags[8].ti_Tag = NP_Name;
  317.   tags[8].ti_Data = (ULONG)argv[1],
  318.   tags[9].ti_Tag = NP_CommandName;
  319.   tags[9].ti_Data = (ULONG)argv[1],
  320.   tags[10].ti_Tag = PPCTASKTAG_STACKSIZE;
  321.   tags[10].ti_Data = 500000;
  322.   tags[11].ti_Tag = NP_StackSize;
  323.   tags[11].ti_Data = 4096;
  324.   tags[12].ti_Tag = PPCTASKTAG_STARTUP_MSG;
  325.   tags[12].ti_Data =(ULONG)startup_msg;
  326.   tags[13].ti_Tag = PPCTASKTAG_STARTUP_MSGDATA;
  327.   tags[13].ti_Data =(ULONG)startup_data;
  328.   tags[14].ti_Tag = PPCTASKTAG_STARTUP_MSGLENGTH;
  329.   tags[14].ti_Data = sizeof(struct StartupData);
  330.   tags[15].ti_Tag = PPCTASKTAG_STARTUP_MSGID;
  331.   tags[15].ti_Data = MSGID_EXIT;
  332.   tags[16].ti_Tag = PPCTASKTAG_EXCEPTIONHOOK;
  333.   tags[16].ti_Data = (ULONG)&exception_hook;
  334.   tags[17].ti_Tag = TAG_END;
  335.  
  336.   ppctask = PPCCreateTask (object, &tags[0]);
  337.   printf ("PPCCreateTask ppctask = %d\n", ppctask);
  338.  
  339. //  Delay (50);
  340.  
  341.   count = 0;
  342.   out_of_range_count = 0;
  343.   other_state_count = 0;
  344.   for (state = TS_INVALID; state <= TS_REMOVED; state++)
  345.     state_count[state] = 0;
  346.   while (PPCGetMessage (M68kPort) == NULL && !task_is_finished) {
  347.     state = PPCGetTaskAttrsTags (ppctask, PPCTASKINFOTAG_STATE, &state, TAG_END);
  348.     switch (state) {
  349.       case TS_INVALID:
  350.         break;
  351.       case TS_ADDED:
  352.         break;
  353.       case TS_RUN:
  354.         tags[0].ti_Tag = TAG_END;
  355.         if (PPCStopTask (ppctask, &tags[0])) {  /* causes an exception */
  356.           /* wait for CTRL_F signal from exception handler */
  357.           sig = Wait (SIGBREAKF_CTRL_F | SIGBREAKF_CTRL_C);
  358.           if (sig & SIGBREAKF_CTRL_C)
  359.             break;
  360.           tags[0].ti_Tag = PPCTASKSTARTTAG_RUN;
  361.           tags[0].ti_Data = TRUE;
  362.           tags[1].ti_Tag = TAG_END;
  363.           PPCStartTask (ppctask, &tags[0]);
  364.         }
  365.         break;
  366.       case TS_READY:
  367.         break;
  368.       case TS_WAIT:
  369.         PPCGetTaskAttrsTags (ppctask, PPCTASKINFOTAG_LR, &pc,
  370.                                       PPCTASKINFOTAG_VALUEPTR, &pc, TAG_END);
  371.         break;
  372.       case TS_EXCEPT:
  373.         break;
  374.       case TS_REMOVED:
  375.         break;
  376.       default:
  377.         break;
  378.     }
  379.     count++;
  380.     if (state <= TS_REMOVED)
  381.       state_count[state]++;
  382.     else
  383.       other_state_count++;
  384.     if ((node = lookup_info (symbol_root, pc)) != NULL) {
  385.       node->count++;
  386.       name = node->name;
  387.     } else {
  388.       out_of_range_count++;
  389.       name = "out of range";
  390.     }
  391. //      printf ("pc = %08x, %s\n", pc, name);
  392. //    }
  393.     Delay (20);  /* or WaitTOF() */
  394.   }
  395.  
  396.   printf ("\nAddress\t\tSize\t\tCount\tName\n");
  397.   print_tree (symbol_root);
  398.  
  399.   for (state = TS_INVALID; state <= TS_REMOVED; state++)
  400.     printf ("%s state count = %d\n", StateString[state], state_count[state]);
  401.   printf ("other state count   = %d\n", other_state_count);
  402.   printf ("out of range count  = %d\n", out_of_range_count);
  403.   printf ("total count         = %d\n", count);
  404.  
  405.   return 0;
  406. }
  407.  
  408. /**********************************************************************/
  409.