home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #16 / NN_1992_16.iso / spool / comp / unix / aix / 8290 < prev    next >
Encoding:
Text File  |  1992-07-29  |  8.2 KB  |  220 lines

  1. Path: sparky!uunet!vnet.ibm.com
  2. From: pgainer@vnet.ibm.com (Patrick Gainer)
  3. Message-ID: <19920729.053004.4@almaden.ibm.com>
  4. Date: Wed, 29 Jul 92 08:00:02 EDT
  5. Newsgroups: comp.unix.aix
  6. Subject: Re: more dynamic loading problems...
  7. Organization: IBM - Toronto Lab
  8. Disclaimer: This posting represents the poster's views, not those of IBM
  9. News-Software: UReply 3.0
  10. References: <45808@shamash.cdc.com>
  11. Lines: 207
  12.  
  13. In <45808@shamash.cdc.com> Paul Dokas x4629 writes:
  14. >I thought that I had solved my problems with dynamic loading, but things
  15. >still aren't working properly.  It seems that when I create a dynamically
  16. >loadable module, that the value returned by nlist() is not always the
  17. >correct offset to the begining of the routine.  The included code for
  18. >example creates a dynamically loadable module with 2 functions 'a_function()'
  19. >and 'b_function()'.  Using nm, I find that the symbol 'a_function' has
  20. >a value of 0x54.  But if I use dbx to look at the location pointed to by
  21. >fn_ptr, I find that the value of 'a_function' should really be 0x18!
  22.  
  23. Paul, I can't seem to mail to your address. Here is some code which
  24. works for me. Please note the address calculations in the routine
  25. load_and_bind. Perhaps they are the source of your troubles.
  26.  
  27. Also, I have posted this from a VM system (gasp) and the left and right
  28. square brackets may be corrupted (I can't tell from here but it has happened
  29. before).
  30.  
  31. ================================CUT HERE====================================
  32. /*=========================================================================*/
  33. /*                                                                         */
  34. /* DESCRIPTION:  A quick and dirty prototype of runtime loading and        */
  35. /*               binding.                                                  */
  36. /*                                                                         */
  37. /*                                                                         */
  38. /* Usage: cc -g -o dyload dyload.c  = builds this executable               */
  39. /*        ld -T512 -H512 -e entry_point -lc -o object_file object_file.o   */
  40. /*                                                                         */
  41. /*=========================================================================*/
  42.  
  43. #include <stdio.h>
  44. #include <nlist.h>
  45. #include <malloc.h>
  46.  
  47.  
  48. /* Type definitions */
  49. typedef struct function_t
  50. {
  51.   char                  name[128];       /* function name */
  52.   int                   (*code)();       /* function pointer */
  53.   int                   arr[3];          /* 12 bytes for func descriptor */
  54. } Function;
  55.  
  56. typedef struct nlist n_list;
  57.  
  58.  
  59. /* Function prototype */
  60. int
  61.   load_and_bind(Function   *flist, char   *file);
  62.  
  63.  
  64. main(int   argc, char   **argv)
  65. {
  66.   char                  *libpath="/u/patrick/tools/dyload:.";
  67.   int                   result;
  68.   int                   loop_control=1;
  69.   char                  file_name[128];
  70.   char                  func_name[128];
  71.   Function              flist[2];
  72.  
  73.   /* optional arg for object file name */
  74.   if (argc < 2)
  75.   {
  76.     printf("Enter name of object file to be loaded.\n");
  77.     result = fgets(file_name, 128, stdin);
  78.  
  79.     /* remove carriage return from file name */
  80.     file_name[strlen(file_name)-1] = 0x00;
  81.   }
  82.   else
  83.   {
  84.     strcpy(file_name,argv[1]);
  85.   }
  86.  
  87.   /* load object module, resolve entry point information */
  88.   flist[0].code = load(file_name,0,libpath);
  89.   if (!flist[0].code)
  90.   {
  91.     printf("load call failed. Exiting.\n");
  92.     exit(-1);
  93.   }
  94.  
  95.   do       /* until user quits by setting loop_control == 0 */
  96.   {
  97.     /* get function to execute from user, preface name by a '.' */
  98.     printf("Enter name of function you wish to execute.\n");
  99.     flist[1].name[0] = '.';
  100.     result = fgets(&(flist[1].name[1]), 128, stdin);
  101.  
  102.     /* remove carriage return from file name (added by fgets) */
  103.     flist[1].name[strlen(flist[1].name)-1] = 0x00;
  104.  
  105.     /* hardcode function entry point - bad programming practise */
  106.     strcpy(flist[0].name,".ibm_start");
  107.  
  108.     /* resolve function name and generate a function pointer */
  109.     result = load_and_bind(flist,file_name);
  110.     if (result != 0)
  111.     {
  112.       printf("function name resolving failed. Exiting.\n");
  113.       exit(-2);
  114.     }
  115.  
  116.     /* execute function */
  117.     (flist[1].code)("Test input string",17);
  118.  
  119.     printf("Continue? (Yes == 1)\n");
  120.     fflush(stdin);
  121.     scanf("%d",&loop_control);
  122.     fflush(stdin);
  123.  
  124.   } while (loop_control);
  125.  
  126. }
  127.  
  128.  
  129.  
  130. /*
  131.  * Given a function name (string), this routine generates a function
  132.  * descriptor and a function pointer to that descriptor. All addresses
  133.  * are resolved so that the function pointer can be directly executed
  134.  * by the calling procedure.
  135.  *
  136.  * Parameters:
  137.  *  flist - contains two entries. The first holds the name of the entry
  138.  *          point for the entire module. This is used to calculate a base
  139.  *          address for the function to be resolved. The second contains
  140.  *          the name of the function to be resolved.
  141.  *  file  - contains the name of the object module containing the functions.
  142.  */
  143. int
  144.   load_and_bind(Function   *flist, char   *file)
  145. {
  146.   int           i;
  147.   n_list        *nlptr;
  148.   int           result;
  149.  
  150.  
  151.   /*===================================================================*/
  152.   /* allocate array of 3 nlist structure - 1 for object module header, */
  153.   /* 1 for function we wish to find, and 1 to NULL terminate array.    */
  154.   /*===================================================================*/
  155.   nlptr = (n_list *) calloc(3,sizeof(n_list));
  156.   if (!nlptr)
  157.   {
  158.     return(-3);
  159.   }
  160.  
  161.   /* set nlist name field for object module entry point */
  162.   nlptr[0]._n._n_name = flist[0].name;
  163.  
  164.   /* set nlist name field for function name to be resolved */
  165.   nlptr[1]._n._n_name = flist[1].name;
  166.  
  167.   /* set nlist name field terminator (NULL name) */
  168.   nlptr[2]._n._n_name = "";
  169.  
  170.   /* call nlist to get function offsets from a name list */
  171.   result = nlist(file, nlptr);
  172.   if (result == -1)
  173.   {
  174.     perror("nlist");
  175.     return(-4);
  176.   }
  177.  
  178.   /*=========================================================================*/
  179.   /* Here is where the addresses are resolved. Basically, the nlist call      */
  180.   /* returns with the offsets from the entry point for each function. The     */
  181.   /* entry point address was obtained via the load() call in main.            */
  182.   /*                                                                          */
  183.   /* Each function is associated with something called a function descriptor. */
  184.   /* This structure (12 bytes) contains the function's virtual address in     */
  185.   /* bytes 0 to 3 and the Table Of Contents address for the module in bytes   */
  186.   /* 4-7. Bytes 8-11 are not used. A function pointer is just a pointer to    */
  187.   /* this structure. To resolve a function's runtime address, The TOC entry   */
  188.   /* from the entry point is used (since the TOC is the same for all funcs    */
  189.   /* in a module) but the virtual address must be calculated. The entry_point */
  190.   /* offset (obtained from nlist) is subtracted from the function-to-be-      */
  191.   /* resolved's virtual address. This gives a base address. Then, the         */
  192.   /* function-to-be-resolved's nlist offset is added to this base address to  */
  193.   /* get the function's virtual address. Finally, the function pointer is set */
  194.   /* to point to the function descriptor structure just created.              */
  195.   /*==========================================================================*/
  196.  
  197.   /* copy entry point function descriptor to func-to-be-resolved's descriptor */
  198.   memcpy(flist[1].arr,flist[0].code,12);
  199.  
  200.   /* set function pointer to point to newly obtained function descriptor */
  201.   flist[1].code = (int(*)()) flist[1].arr;
  202.  
  203.   /*==============================================================*/
  204.   /* Subtract the nlist offset for the module from the ptr value  */
  205.   /* in flist[1].arr[0-3]. This will yield a base virtual address.*/
  206.   /*==============================================================*/
  207.   *((int *)flist[1].arr) = *((int *) flist[1].arr) - nlptr[0].n_value;
  208.  
  209.   /*==============================================================*/
  210.   /* Add the nlist offset for this particular symbol to the base  */
  211.   /* virtual address.                                             */
  212.   /*==============================================================*/
  213.   *((int *)flist[1].arr) = *((int *) flist[1].arr) + nlptr[1].n_value;
  214.  
  215.   /* done - free memory and return */
  216.   free(nlptr);
  217.   return(0);
  218. }
  219.  
  220.