OberonLoader.c 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. /*
  2. G.F. 31.01.2017
  3. Loader for statically linked oberon binaries.
  4. Compile command:
  5. gcc -m32 -s -O OberonLoader.c -ldl -o OberonLoader
  6. gcc -m64 -s -O OberonLoader.c -ldl -o OberonLoader
  7. The statically linked oberon binary 'oberon.bin' has to be
  8. appended to this loader by the following A2-command:
  9. UnixBinary.Build oberon.bin -> <program name> ~
  10. */
  11. #include <stdlib.h>
  12. #include <stdio.h>
  13. #include <fcntl.h>
  14. #include <sys/types.h>
  15. #include <sys/mman.h>
  16. #include <sys/uio.h>
  17. #include <unistd.h>
  18. #include <sys/stat.h>
  19. #include <string.h>
  20. #include <dlfcn.h>
  21. #define Offset 16*1024 /* startpos of the appended oberon binary */
  22. #define BlkSize 4*1024
  23. typedef void (*OberonProc)();
  24. typedef void *addr;
  25. typedef unsigned int uint;
  26. typedef unsigned long ulong;
  27. typedef struct { /* cf. Unix.*.Glue.Mod */
  28. /* Oberon --> loader: */
  29. char id[24]; /* must match coreID */
  30. int codesize;
  31. int relocations;
  32. OberonProc entry; /* Glue.Init0 */
  33. /* loader --> Oberon: */
  34. addr *dlopenaddr;
  35. addr *dlcloseaddr;
  36. addr *dlsymaddr;
  37. int *argc;
  38. addr *argv;
  39. addr *env;
  40. addr *cout;
  41. } *Header;
  42. #if defined(__LP64__) || defined(_LP64)
  43. char *coreID = "Oberon64G.binary"; /* cf. Unix.Glue.Mod */
  44. #else
  45. char *coreID = "Oberon32G.binary"; /* cf. Unix.Glue.Mod */
  46. #endif
  47. addr heap;
  48. uint heapsize;
  49. int fd;
  50. void cout( char c ) {
  51. char buf[8];
  52. buf[0] = c;
  53. write( 1, &buf, 1 );
  54. }
  55. uint ReadInteger( ) {
  56. union {
  57. char buf[4];
  58. uint i;
  59. } u;
  60. read( fd, &u.buf, 4 );
  61. return (u.i);
  62. }
  63. void Relocate( uint relocations ) {
  64. addr *a;
  65. uint i;
  66. for (i=0; i<relocations; i++) {
  67. a = heap + ReadInteger();
  68. *a += (ulong)heap;
  69. }
  70. }
  71. char *which_path(const char *name) {
  72. char *tname, *tok, *path;
  73. path = strdup(getenv("PATH"));
  74. if (NULL == path) return NULL;
  75. tok = strtok(path, ":");
  76. while (tok) {
  77. tname = malloc(strlen(tok) + 2 + strlen(name));
  78. sprintf(tname, "%s/%s", tok, name);
  79. if (0 == access(tname, X_OK)) { free(path); return tname; }
  80. free(tname);
  81. tok = strtok(NULL, ":");
  82. }
  83. free(path);
  84. return NULL;
  85. }
  86. int main( int argc, char *argv[], char *env[] ) {
  87. int r, n, binsize, relocations;
  88. size_t fsize;
  89. struct stat sb;
  90. Header header;
  91. char *path, *buf;
  92. fd = open( *argv, O_RDONLY );
  93. if (fd < 0) {
  94. /* find myself in PATH */
  95. path = which_path(*argv);
  96. fd = open(path, O_RDONLY);
  97. }
  98. r = fstat( fd, &sb );
  99. if ( sb.st_size < Offset+2048 ) {
  100. fprintf( stderr, "%s: missing appended Oberon binary\n", *argv );
  101. exit( 2 );
  102. }
  103. r = lseek( fd, Offset, SEEK_SET );
  104. buf = malloc( 512 );
  105. n = read( fd, buf, 256 );
  106. header = (Header)buf;
  107. if (strcmp(header->id, coreID) != 0) {
  108. fprintf( stderr, "wrong Oberon headerId: got '%s', expected '%s'\n", header->id, coreID );
  109. exit( 2 );
  110. }
  111. binsize = header->codesize;
  112. relocations = header->relocations;
  113. free( buf );
  114. heapsize = BlkSize;
  115. while (heapsize < binsize) heapsize += BlkSize;
  116. r = lseek( fd, Offset, SEEK_SET );
  117. r = posix_memalign( &heap, BlkSize, heapsize );
  118. if (mprotect( heap, heapsize, PROT_READ|PROT_WRITE|PROT_EXEC) != 0)
  119. perror("mprotect");
  120. n = read( fd, heap, binsize );
  121. Relocate( relocations );
  122. header = (Header)heap;
  123. *(header->dlopenaddr) = dlopen;
  124. *(header->dlcloseaddr) = dlclose;
  125. *(header->dlsymaddr) = dlsym;
  126. *(header->argc) = argc;
  127. *(header->argv) = argv;
  128. *(header->env) = env;
  129. *(header->cout) = cout;
  130. header->entry();
  131. return (0);
  132. }