blackbox.c 14 KB

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