blackbox.c 13 KB

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