blackbox.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634
  1. /*
  2. * C-startup and loader for BlackBox
  3. * Implemented as the StdLoader.
  4. */
  5. #include <sys/mman.h>
  6. #include <dlfcn.h>
  7. #include <stdio.h>
  8. #include <stdlib.h>
  9. #include <string.h>
  10. #include <errno.h>
  11. #include <fcntl.h>
  12. /* the exact size (in bytes) of the executable part of the file. */
  13. /* this constant needs to be updated everytime a change is made to this file */
  14. #define exeSize 17008
  15. /* fixup types */
  16. #define absolute 100
  17. #define relative 101
  18. #define copy 102
  19. #define table 103
  20. #define tableend 104
  21. #define deref 105
  22. #define halfword 106
  23. /* import types */
  24. #define mConst 0x1
  25. #define mTyp 0x2
  26. #define mVar 0x3
  27. #define mProc 0x4
  28. #define mExported 4
  29. #define any 1000000
  30. #define init 0x10000
  31. /* set to printf to debug and donothing to avoid debugging */
  32. #define dprintf donothing
  33. typedef void (*BodyProc)();
  34. typedef char String[256];
  35. typedef struct Type {
  36. int size;
  37. struct Module* mod;
  38. int id;
  39. int base[16]; /* should be ARRAY 16 OF TYPE */
  40. int fields; /* should be Directory* */
  41. int ptroffs[any];
  42. } Type;
  43. typedef struct Object{
  44. int fprint;
  45. int offs;
  46. int id;
  47. Type* ostruct;
  48. } Object;
  49. typedef struct Directory{
  50. int num;
  51. Object obj[any];
  52. } Directory;
  53. typedef struct Module{ /* has to be exact copy of Kernel.Module */
  54. struct Module *next;
  55. int opts;
  56. int refcnt;
  57. short compTime[6], loadTime[6];
  58. int ext;
  59. int term; /* actually a pointer to type Command */
  60. int nofimps, nofptrs;
  61. int csize, dsize, rsize;
  62. int code, data, refs;
  63. int procBase, varBase; /* meta base addresses */
  64. char* names; /* names[0] = 0X */
  65. int* ptrs;
  66. struct Module* imports;
  67. Directory* export;
  68. char name[256];
  69. } Module;
  70. typedef struct ImpList
  71. {
  72. struct ImpList* next;
  73. String name;
  74. } ImpList;
  75. typedef struct ModSpec
  76. {
  77. ImpList* imp;
  78. String name;
  79. int start, hs, ms, ds, cs, vs, mad, dad;
  80. } ModSpec;
  81. typedef struct BootInfo
  82. {
  83. Module* modList;
  84. int argc;
  85. char** argv;
  86. } BootInfo;
  87. const char bbfile[] = "./bb.boot";
  88. FILE* f;
  89. int nofMods;
  90. String kernel, mainmod;
  91. ModSpec mod;
  92. Module *modlist;
  93. BootInfo* bootInfo;
  94. int newRecAdr, newArrAdr;
  95. int newRecFP, newArrFP;
  96. int zerofd;
  97. int donothing(char* fmt, ...)
  98. {
  99. }
  100. void DumpMod()
  101. {
  102. dprintf("\n\n---- Mod info:\n");
  103. dprintf(" hs, ms, ds, cs, vs = %d, %d, %d, %d, %d\n",
  104. mod.hs, mod.ms, mod.ds, mod.cs, mod.vs);
  105. dprintf(" mad, dad = %d, %d\n\n", mod.mad, mod.dad);
  106. }
  107. void RegisterModule()
  108. {
  109. Module* m;
  110. m = (Module*)mod.dad;
  111. m->next = modlist;
  112. modlist = m;
  113. /*
  114. if (modlist == NULL){
  115. modlist = m;
  116. } else {
  117. last->next = m;
  118. last = m;
  119. }
  120. last->next = NULL;
  121. */
  122. dprintf("Registred module %s\n", mod.name);
  123. }
  124. void PrintMods()
  125. {
  126. Module* ml;
  127. ml = modlist;
  128. dprintf("Loaded Modules\n");
  129. while (ml != NULL){
  130. dprintf("mod name: %s\n", ml->name);
  131. ml = ml->next;
  132. }
  133. dprintf("end of list\n");
  134. }
  135. Module* ThisModule(char* name)
  136. {
  137. Module* ml;
  138. ml = modlist;
  139. while ((ml != NULL) && (strcmp(ml->name, name) != 0)){
  140. ml = ml->next;
  141. }
  142. return ml;
  143. }
  144. Object* ThisObject(Module* mod, char* name)
  145. {
  146. int l, r, m;
  147. char* p;
  148. l = 0; r = mod->export->num;
  149. while (l < r){
  150. m = (l + r) / 2;
  151. p = (char*) &(mod->names[mod->export->obj[m].id / 256]);
  152. if (strcmp(p, name) == 0)
  153. return (Object*)&(mod->export->obj[m]);
  154. if (strcmp(p, name) < 0)
  155. l = m + 1;
  156. else
  157. r = m;
  158. }
  159. return NULL;
  160. }
  161. Object* ThisDesc(Module* mod, int fprint)
  162. {
  163. int i, n;
  164. i = 0; n = mod->export->num;
  165. while ((i < n) && (mod->export->obj[i].id / 256 == 0))
  166. {
  167. if (mod->export->obj[i].offs == fprint)
  168. return (Object*)&(mod->export->obj[i]);
  169. i++;
  170. }
  171. return NULL;
  172. }
  173. int LoadDll (char* name)
  174. {
  175. void *handle;
  176. dprintf("loading: %s\n", name);
  177. if ((handle = dlopen(name, RTLD_LAZY + RTLD_GLOBAL)) == NULL) {
  178. printf("LoadDll: failed to load lib %s\n", name);
  179. printf(" - dlerror: %s\n", dlerror());
  180. exit(-1);
  181. }
  182. return handle != NULL;
  183. }
  184. int ThisDllObj (int mode, int fprint, char* dll, char* name)
  185. {
  186. void *handle;
  187. int ad = 0;
  188. if ((mode == mVar) || (mode == mProc)){
  189. if ((handle = dlopen(dll, RTLD_LAZY + RTLD_GLOBAL)) == NULL) {
  190. printf("ThisDllObj: lib %s not found\n", dll);
  191. printf(" - dlerror: %s\n", dlerror());
  192. exit(-1);
  193. } else {
  194. ad = (int)dlsym((void *) handle, name);
  195. if (ad == 0) {
  196. printf("ThisDllObj: symbol %s not found\n", name); exit(-1);
  197. }
  198. }
  199. }
  200. return ad;
  201. }
  202. int Read4 ()
  203. {
  204. unsigned char b;
  205. int w;
  206. b = fgetc(f); w = b % 256;
  207. b = fgetc(f); w = w + 0x100 * (b % 256);
  208. b = fgetc(f); w = w + 0x10000 * (b % 256);
  209. b = fgetc(f); w = w + 0x1000000 * b;
  210. return w;
  211. }
  212. int RNum()
  213. {
  214. char b;
  215. int s, y;
  216. s = 0; y = 0;
  217. b = fgetc(f);
  218. while (b < 0)
  219. {
  220. y = y + ((b + 128) << s);
  221. s = s + 7;
  222. b = fgetc(f);
  223. }
  224. return (((b + 64) % 128 - 64) << s) + y;
  225. }
  226. void ReadName (char* str)
  227. {
  228. unsigned char b;
  229. int i;
  230. i = 0; b = fgetc(f);
  231. while (b != 0)
  232. {
  233. str[i] = b; i++; b = fgetc(f);
  234. }
  235. str[i] = 0;
  236. }
  237. void Fixup (int adr)
  238. {
  239. int link, offset, linkadr, n, x, t;
  240. dprintf("fixup: %X ", adr);
  241. link = RNum();
  242. while (link != 0)
  243. {
  244. offset = RNum();
  245. dprintf("+%d: ", offset);
  246. while (link != 0)
  247. {
  248. if (link > 0)
  249. {
  250. dprintf("c");
  251. linkadr = mod.mad + mod.ms + link;
  252. }
  253. else
  254. {
  255. dprintf("d");
  256. link = -link;
  257. if (link < mod.ms)
  258. linkadr = mod.mad + link;
  259. else
  260. linkadr = mod.dad + link - mod.ms;
  261. }
  262. dprintf("%X ", link);
  263. /*
  264. t = *(char*)(linkadr + 3);
  265. n = *(int*)linkadr;
  266. n = n << 8; n = n >> 8;
  267. */
  268. x = *(int*)linkadr;
  269. t = x / 0x1000000;
  270. n = (x + 0x800000) % 0x1000000 - 0x800000;
  271. switch (t) {
  272. case absolute: x = adr + offset; break;
  273. case relative: x = adr + offset - linkadr -4; break;
  274. case copy: x = *(int*)(adr + offset); break;
  275. case table: x = adr + n; n = link + 4; break;
  276. case tableend: x = adr + n; n = 0; break;
  277. case deref: x = *(int*)(adr + 2); x = x + offset; break;
  278. case halfword:
  279. printf("fixup: halfword not implemented\n");
  280. break;
  281. default:
  282. printf("fixup error(link=%d, offset=%d, linkadr=%d, t=%d, x=%d)\n",
  283. link, offset, linkadr, t, x);
  284. return;
  285. }
  286. *(int*)linkadr = x;
  287. link = n;
  288. }
  289. link = RNum();
  290. }
  291. dprintf("\n");
  292. }
  293. int ReadBootHeader()
  294. {
  295. int tag, version;
  296. fseek(f, exeSize, SEEK_SET);
  297. tag = Read4();
  298. version = Read4();
  299. if ((tag != 0x3A4B5C6D) || (version != 0))
  300. {
  301. return 0;
  302. }
  303. nofMods = Read4();
  304. dprintf("Linked modules: %d\n", nofMods);
  305. ReadName(kernel);
  306. dprintf("kernel: %s\n", kernel);
  307. ReadName(mainmod);
  308. dprintf("main: %s\n", mainmod);
  309. newRecFP = Read4(); newRecAdr = 0;
  310. newArrFP = Read4(); newArrAdr = 0;
  311. mod.start = ftell(f);
  312. return 1;
  313. }
  314. void * MemAlloc (size_t len)
  315. {
  316. void * res;
  317. res = mmap(0, len, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_ANON, zerofd, 0);
  318. if (res == MAP_FAILED) {
  319. res = NULL;
  320. } else {
  321. bzero(res, len);
  322. }
  323. return res;
  324. }
  325. int ReadHeader ()
  326. {
  327. int ofTag, i, nofImps, processor;
  328. char str[80];
  329. ImpList *imp, *last;
  330. char* n;
  331. ofTag = Read4();
  332. if (ofTag != 0x6F4F4346)
  333. {
  334. printf("wrong object file version\n");
  335. return 0;
  336. }
  337. processor = Read4();
  338. mod.hs = Read4();
  339. mod.ms = Read4();
  340. mod.ds = Read4();
  341. mod.cs = Read4();
  342. mod.vs = Read4();
  343. dprintf("File tag: %d ", ofTag); dprintf("Processor: %d\n", processor);
  344. dprintf("Header size: %d ", mod.hs);
  345. dprintf("Meta size: %d ", mod.ms);
  346. dprintf("Desc size: %d ", mod.ds );
  347. dprintf("Code size: %d ", mod.cs);
  348. dprintf("Data size: %d\n", mod.vs);
  349. nofImps = RNum(); dprintf("Nof imports: %d\n", nofImps);
  350. ReadName(mod.name); dprintf("Module name: %s\n", mod.name);
  351. mod.imp = NULL;
  352. for (i = 0; i < nofImps; i++)
  353. {
  354. imp = (ImpList*)MemAlloc(sizeof(ImpList));
  355. ReadName(imp->name);
  356. if (mod.imp == NULL)
  357. mod.imp = imp;
  358. else
  359. last->next = imp;
  360. last = imp;
  361. last->next = NULL;
  362. dprintf("Import %d: %s\n", i, imp->name);
  363. if ((imp->name[0] == '$') && (imp->name[1] == '$'))
  364. strcpy(imp->name, "Kernel");
  365. if (imp->name[0] == '$'){
  366. n = imp->name;
  367. n++;
  368. if (!LoadDll(n)){
  369. printf("Could not load lib: %s\n", (char *)(&(imp->name[1])));
  370. return 0;
  371. }
  372. }
  373. }
  374. dprintf("Pos: %d\n", ftell(f));
  375. return 1;
  376. }
  377. int ReadModule ()
  378. {
  379. char *dp, *mp;
  380. unsigned int cnt;
  381. ImpList* imp;
  382. int x, fp, opt, link, ofp, imptab, a;
  383. Module *desc, *k;
  384. String name;
  385. Object* obj;
  386. int isLib;
  387. char* im;
  388. mod.dad = (int) MemAlloc(mod.ds);
  389. mod.mad = (int) MemAlloc(mod.ms + mod.cs + mod.vs);
  390. if ((mod.dad == 0) || (mod.mad == 0))
  391. {
  392. printf("BootLoader: Couldn't initalize heap\n");
  393. free((void*)mod.dad);
  394. free((void*)mod.mad);
  395. return 0;
  396. }
  397. dp = (char*) mod.dad;
  398. mp = (char*) mod.mad;
  399. fseek(f, mod.start + mod.hs, SEEK_SET);
  400. dprintf("ReadModule after fseek pos: %d\n", ftell(f));
  401. cnt = fread(mp, 1, mod.ms, f);
  402. dprintf("Read meta bulk (%d bytes. New pos: %d)\n", cnt, ftell(f));
  403. cnt = fread(dp, 1, mod.ds, f);
  404. dprintf("Read desc bulk (%d bytes. New pos: %d)\n", cnt, ftell(f));
  405. mp = (char*)(mod.mad + mod.ms);
  406. cnt = fread(mp, 1, mod.cs, f);
  407. dprintf("Read code bulk (%d bytes. New pos: %d)\n", cnt, ftell(f));
  408. DumpMod();
  409. dprintf("before fixup: pos = %d\n", ftell(f));
  410. if ((!newRecAdr) || (!newArrAdr)){
  411. k = ThisModule(kernel);
  412. if (k != NULL){
  413. /* obj = ThisDesc(k, newRecFP);*/
  414. obj = ThisObject(k, "NewRec");
  415. if (obj != NULL)
  416. newRecAdr = k->procBase + obj->offs;
  417. /* obj = ThisDesc(k, newArrFP);*/
  418. obj = ThisObject(k, "NewArr");
  419. if (obj != NULL)
  420. newArrAdr = k->procBase + obj->offs;
  421. dprintf("newRecFP: %X newArrFP: %X\n", newRecFP, newArrFP);
  422. dprintf("newRecAdr: %X newArrAdr: %X\n", newRecAdr, newArrAdr);
  423. } else {
  424. dprintf("no kernel before %s.\n", mod.name);
  425. }
  426. }
  427. Fixup(newRecAdr);
  428. Fixup(newArrAdr);
  429. Fixup(mod.mad);
  430. Fixup(mod.dad);
  431. Fixup(mod.mad + mod.ms);
  432. Fixup(mod.mad + mod.ms + mod.cs);
  433. dprintf("after fixup: pos = %d\n", ftell(f));
  434. imp = mod.imp; imptab = (int)((Module*)(mod.dad))->imports;
  435. while (imp != NULL){
  436. x = RNum();
  437. if ((imp->name[0] == '$') && (imp->name[1] == '$'))
  438. printf("should be Kerneln");
  439. if (imp->name[0] == '$')
  440. isLib = 1;
  441. else{
  442. isLib = 0;
  443. desc = ThisModule(imp->name);
  444. if (desc == NULL){
  445. printf("invalid import list\n");
  446. return 0;
  447. }
  448. }
  449. while (x != 0) {
  450. ReadName(name); fp = RNum(); opt = 0;
  451. if (!isLib) {
  452. if (name[0] == 0)
  453. obj = ThisDesc(desc, fp);
  454. else
  455. obj = ThisObject(desc, name);
  456. if ((obj != NULL) && (obj->id % 16 == x)){
  457. ofp = obj->fprint;
  458. switch (x){
  459. case mTyp:
  460. opt = RNum();
  461. if (opt % 2 == 1) ofp = obj->offs;
  462. if ((opt > 1) && ((obj->id / 16) % 16 != mExported)){
  463. printf("object not found (%s)\n", imp->name);
  464. return 0;
  465. }
  466. Fixup((int)obj->ostruct);
  467. break;
  468. case mVar:
  469. Fixup(desc->varBase + obj->offs);
  470. break;
  471. case mProc:
  472. Fixup(desc->procBase + obj->offs);
  473. }
  474. if (ofp != fp){
  475. printf("illigal foot print (%s)\n", imp->name);
  476. return 0;
  477. }
  478. } else {
  479. if (obj == NULL) printf("obj == NULL\n");
  480. printf("descriptor not found (%s, x: %d, id: %d)\n", name, x, obj->id);
  481. return 0;
  482. }
  483. }else{
  484. if ((x == mVar) || (x == mProc)){
  485. im = imp->name;
  486. im++;
  487. a = ThisDllObj(x, fp, im, name);
  488. if (a != 0)
  489. Fixup(a);
  490. else{
  491. printf("ReadModule: Object not found: %s\n", name);
  492. return 0;
  493. }
  494. } else {
  495. if (x == mTyp) {
  496. opt = RNum();
  497. x = RNum();
  498. if (x != 0) {
  499. printf("ReadModule: Object not found: %s\n", name);
  500. return 0;
  501. }
  502. }
  503. }
  504. }
  505. x = RNum();
  506. }
  507. *(int*)imptab = (int)desc; imptab += 4;
  508. imp = imp->next;
  509. }
  510. mod.start = ftell(f);
  511. return 1;
  512. }
  513. int main (int argc, char *argv[])
  514. {
  515. int i, ok;
  516. BodyProc body;
  517. int callBackAdr;
  518. Module *k, *m;
  519. zerofd = open("/dev/zero", O_RDWR);
  520. if (zerofd == -1) {
  521. printf("open /dev/zero failed: %s\n", strerror(errno));
  522. return 101;
  523. }
  524. modlist = NULL;
  525. dprintf("initializing BlackBox for Linux...\n");
  526. /*f = fopen(bbfile, "rb");*/
  527. f = fopen(argv[0], "r");
  528. if (f != NULL)
  529. {
  530. if (ReadBootHeader())
  531. {
  532. i = 0; ok = 1;
  533. while ((i < nofMods) && (ok)){
  534. ok = ReadHeader();
  535. if (ok) {
  536. ok = ReadModule();
  537. if (ok)
  538. RegisterModule();
  539. else
  540. printf("Incorrect module: %s\n", mod.name);
  541. } else
  542. printf("Incorrect header: %s\n", mod.name);
  543. i++;
  544. }
  545. fclose(f);
  546. if (ok) {
  547. k = ThisModule(kernel);
  548. m = ThisModule(mainmod);
  549. if (k == NULL)
  550. printf("no kernel\n");
  551. else
  552. {
  553. if (m == NULL)
  554. printf("no main module");
  555. else
  556. {
  557. /* assign the boot info to first variable in Kernel */
  558. bootInfo = MemAlloc(sizeof(BootInfo));
  559. bootInfo->modList = modlist;
  560. bootInfo->argc = argc;
  561. bootInfo->argv = argv;
  562. *((int*)(k->varBase)) = (int)bootInfo;
  563. dprintf("before body\n");
  564. body = (BodyProc)(m->code);
  565. k->opts = k->opts | init; /* include init in opts */
  566. body();
  567. dprintf("after body\n");
  568. }
  569. }
  570. PrintMods();
  571. }
  572. } else
  573. printf("Invalid BlackBox executable, make sure that the constant exeSize is correctly set\n");
  574. } else
  575. printf("Couldn't find file: %s\n", bbfile);
  576. }