2
0

OberonLoader.c 3.4 KB

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