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