ElfLinker16.txt 54 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740
  1. MODULE DevElfLinker;
  2. (* THIS IS TEXT COPY OF OpenBUGS Dev/Mod/ElfLinker16.odc *)
  3. (* DO NOT EDIT *)
  4. (*
  5. DevElfLinker version compatible with BlackBox Component Builder release 1.6.
  6. This module will replace DevElfLinker, once the final version of BlackBox 1.6 will be released.
  7. *)
  8. IMPORT
  9. Strings,
  10. Kernel, Files, Dialog,
  11. TextMappers,
  12. StdLog, DevCommanders;
  13. CONST
  14. NewRecFP = 4E27A847H;
  15. NewArrFP = 76068C78H;
  16. OFdir = "Code";
  17. SYSdir = "System";
  18. (* meta interface consts *)
  19. mConst = 1; mTyp = 2; mVar = 3; mProc = 4;
  20. mInternal = 1; mExported = 4;
  21. (* mod desc fields *)
  22. modOpts = 4; modRefcnt = 8; modTerm = 40; modNames = 84; modImports = 92; modExports = 96;
  23. (* .dynsym entries *)
  24. stbLocal = 0; stbGlobal = 1;
  25. sttNotype = 0; sttObject = 1; sttFunc = 2; sttSection = 3;
  26. shnUnd = 0; shnAbs = 0FFF1H;
  27. fixup = 0;
  28. noSymbol = MIN(INTEGER);
  29. noAddr = MIN(INTEGER);
  30. firstDllSymbolVal = 12;
  31. (* distinguished section header indexes. *)
  32. textIndexVal = 1; (* index of the .text section header in the section header table *)
  33. rodataIndexVal = 3; (* index of the .rodata section header in the section header table *)
  34. dynsymIndexVal = 5; (* index of the .dynsym section header in the section header table *)
  35. dynstrIndexVal = 6; (* index of the .dynstr section header in the section header table *)
  36. (* fixed elements dimensions *)
  37. elfHeaderSizeVal = 52; (* size of the ELF file header *)
  38. shEntrySizeVal = 40; (* size of an entry in the section header table *)
  39. dynsymEntrySizeVal = 16; (* size of a symbol table entry *)
  40. dynamicEntrySizeVal = 8; (* size of an entry in the dynamic section *)
  41. gotEntrySizeVal = 4; (* size of an entry in the got section *)
  42. relEntrySizeVal = 8; (* size of an entry in a relocation section *)
  43. phEntrySizeVal = 32; (* size of an entry in the program header *)
  44. shNumVal = 12; (* number of entries in the section header table. See WriteSectionHeaderTable *)
  45. shStrndxVal = shNumVal - 1; (* index of the string table for section names. See WriteSectionHeaderTable *)
  46. phNumVal = 3; (* number of entries in the program header table *)
  47. (* sections alignments (in bytes) *)
  48. textAlign = 4H;
  49. dynsymAlign = 4H;
  50. dynstrAlign = 1H;
  51. hashAlign = 4H;
  52. gotAlign = 4H;
  53. dynamicAlign = 4H;
  54. shstrtabAlign = 1H;
  55. bssAlign = 4H;
  56. rodataAlign = 8H;
  57. relAlign = 4H;
  58. pageSize = 1000H; (* I386 page size *)
  59. r38632 = 1; r386pc32 = 2; r386Relative = 8; (* ELF relocation types *)
  60. TYPE
  61. Name = ARRAY 40 OF SHORTCHAR;
  62. Export = POINTER TO RECORD
  63. next: Export;
  64. name: Name;
  65. adr: INTEGER
  66. END;
  67. Module = POINTER TO RECORD
  68. next: Module;
  69. name: Name;
  70. fileName: Files.Name;
  71. file: Files.File;
  72. hs, ms, ds, cs, vs, ni, ma, ca, va: INTEGER;
  73. dll, intf: BOOLEAN;
  74. exp: Export;
  75. imp: POINTER TO ARRAY OF Module;
  76. data: POINTER TO ARRAY OF BYTE
  77. END;
  78. Strtab = RECORD
  79. tab: ARRAY 4096 OF SHORTCHAR;
  80. cur: INTEGER
  81. END;
  82. Relocation = RECORD
  83. offset, type: INTEGER
  84. END;
  85. RelTab = RECORD
  86. tab: ARRAY 65536 OF Relocation;
  87. cur: INTEGER
  88. END;
  89. Section = RECORD
  90. fileOffset,
  91. memOffset,
  92. size: INTEGER
  93. END;
  94. VAR
  95. W: TextMappers.Formatter;
  96. Out: Files.File;
  97. R: Files.Reader;
  98. Ro: Files.Writer;
  99. error, isDll, isStatic: BOOLEAN;
  100. modList, kernel, main, last, impg, impd: Module;
  101. numMod, lastTerm: INTEGER;
  102. firstExp, lastExp: Export;
  103. CodeSize, DataSize, ConSize: INTEGER;
  104. maxCode, numExp: INTEGER;
  105. newRec, newArr: Name;
  106. code: POINTER TO ARRAY OF BYTE;
  107. (* fixup positions *)
  108. entryPos,
  109. expPos,
  110. shstrtabPos,
  111. finiPos: INTEGER;
  112. (* sections *)
  113. text, reltext, relrodata, rodata, dynstr, shstrtab, hash, got, dynsym, dynamic, bss: Section;
  114. (* distinguished file and memory offsets *)
  115. shOffsetVal, (* section header table file offset *)
  116. phOffsetVal, (* program header table file offset *)
  117. finiMemOffsetVal: INTEGER; (* memory offset (aka virtual address) of the finalization code (CLOSE sections) *)
  118. dynsymInfoVal, (* value of the info field for the .dynsym section *)
  119. sonameStrIndexVal: INTEGER; (* string table index of the name of hte library *)
  120. (* segment dimensions *)
  121. textSegmentSizeVal,
  122. dataSegmentSizeVal,
  123. dynamicSegmentSizeVal: INTEGER;
  124. headerstrtab, dynstrtab: Strtab;
  125. hashtab: ARRAY 256 OF Name;
  126. neededIdx: ARRAY 256 OF INTEGER;
  127. relTextTab, relRodataTab: RelTab;
  128. soName: Name;
  129. doWrite: BOOLEAN;
  130. PROCEDURE (VAR t: Strtab) AddName (IN s: ARRAY OF SHORTCHAR; OUT idx: INTEGER), NEW;
  131. VAR i: INTEGER;
  132. BEGIN
  133. ASSERT((t.cur + LEN(s$)) <= LEN(t.tab), 20); (* table buffer not large enough: TODO enlarge? *)
  134. idx := t.cur;
  135. i := 0;
  136. WHILE s[i] # 0X DO
  137. t.tab[t.cur] := s[i];
  138. INC(i); INC(t.cur)
  139. END;
  140. t.tab[t.cur] := s[i]; (* copy the 0X *)
  141. INC(t.cur)
  142. END AddName;
  143. PROCEDURE (VAR t: RelTab) Add (offset, type: INTEGER), NEW;
  144. BEGIN
  145. ASSERT(t.cur < LEN(t.tab), 20); (* table buffer not large enough: TODO enlarge? *)
  146. t.tab[t.cur].offset := offset;
  147. t.tab[t.cur].type := type;
  148. INC(t.cur)
  149. END Add;
  150. PROCEDURE AddNeededIdx (idx: INTEGER);
  151. VAR i, len: INTEGER;
  152. BEGIN
  153. ASSERT(idx > 0, 20); (* index must be positive *)
  154. len := LEN(neededIdx);
  155. i := 0;
  156. WHILE (i # len) & (neededIdx[i] # 0) DO INC(i) END;
  157. IF i # len THEN
  158. neededIdx[i] := idx
  159. ELSE
  160. HALT(21) (* no more space for indexes *)
  161. END
  162. END AddNeededIdx;
  163. PROCEDURE ThisFile (modname: ARRAY OF CHAR): Files.File;
  164. VAR dir, name: Files.Name; loc: Files.Locator; f: Files.File;
  165. BEGIN
  166. Kernel.SplitName(modname, dir, name);
  167. Kernel.MakeFileName(name, Kernel.objType);
  168. loc := Files.dir.This(dir); loc := loc.This(OFdir);
  169. f := Files.dir.Old(loc, name, TRUE);
  170. IF (f = NIL) & (dir = "") THEN
  171. loc := Files.dir.This(SYSdir); loc := loc.This(OFdir);
  172. f := Files.dir.Old(loc, name, TRUE)
  173. END;
  174. RETURN f
  175. END ThisFile;
  176. PROCEDURE Read4 (VAR x: INTEGER);
  177. VAR b: BYTE;
  178. BEGIN
  179. R.ReadByte(b); x := b MOD 256;
  180. R.ReadByte(b); x := x + 100H * (b MOD 256);
  181. R.ReadByte(b); x := x + 10000H * (b MOD 256);
  182. R.ReadByte(b); x := x + 1000000H * b
  183. END Read4;
  184. PROCEDURE ReadName (VAR name: ARRAY OF SHORTCHAR);
  185. VAR i: INTEGER; b: BYTE;
  186. BEGIN i := 0;
  187. REPEAT
  188. R.ReadByte(b); name[i] := SHORT(CHR(b)); INC(i)
  189. UNTIL b = 0
  190. END ReadName;
  191. PROCEDURE RNum (VAR i: INTEGER);
  192. VAR b: BYTE; s, y: INTEGER;
  193. BEGIN
  194. s := 0; y := 0; R.ReadByte(b);
  195. WHILE b < 0 DO INC(y, ASH(b + 128, s)); INC(s, 7); R.ReadByte(b) END;
  196. i := ASH((b + 64) MOD 128 - 64, s) + y
  197. END RNum;
  198. PROCEDURE WriteCh (ch: SHORTCHAR);
  199. BEGIN
  200. IF doWrite THEN
  201. Ro.WriteByte(SHORT(ORD(ch)))
  202. END
  203. END WriteCh;
  204. PROCEDURE Write2 (x: INTEGER);
  205. BEGIN
  206. IF doWrite THEN
  207. Ro.WriteByte(SHORT(SHORT(x MOD 256))); x := x DIV 256;
  208. Ro.WriteByte(SHORT(SHORT(x MOD 256)))
  209. END
  210. END Write2;
  211. PROCEDURE Write4 (x: INTEGER);
  212. BEGIN
  213. IF doWrite THEN
  214. Ro.WriteByte(SHORT(SHORT(x MOD 256))); x := x DIV 256;
  215. Ro.WriteByte(SHORT(SHORT(x MOD 256))); x := x DIV 256;
  216. Ro.WriteByte(SHORT(SHORT(x MOD 256))); x := x DIV 256;
  217. Ro.WriteByte(SHORT(SHORT(x MOD 256)))
  218. END
  219. END Write4;
  220. PROCEDURE WriteBytes (IN x: ARRAY OF BYTE; beg, len: INTEGER);
  221. BEGIN
  222. IF doWrite THEN
  223. Ro.WriteBytes(x, beg, len)
  224. END
  225. END WriteBytes;
  226. PROCEDURE Align (alignment: INTEGER);
  227. BEGIN
  228. WHILE Ro.Pos() MOD alignment # 0 DO WriteCh(0X) END
  229. END Align;
  230. PROCEDURE Aligned (pos, alignment: INTEGER): INTEGER;
  231. BEGIN
  232. RETURN (pos + (alignment - 1)) DIV alignment * alignment
  233. END Aligned;
  234. PROCEDURE Put (mod: Module; a, x: INTEGER);
  235. BEGIN
  236. ASSERT((mod.data # NIL) & ((a >= 0) & (a <= LEN(mod.data))), 20);
  237. mod.data[a] := SHORT(SHORT(x)); INC(a); x := x DIV 256;
  238. mod.data[a] := SHORT(SHORT(x)); INC(a); x := x DIV 256;
  239. mod.data[a] := SHORT(SHORT(x)); INC(a); x := x DIV 256;
  240. mod.data[a] := SHORT(SHORT(x))
  241. END Put;
  242. PROCEDURE Get (mod: Module; a: INTEGER; VAR x: INTEGER);
  243. BEGIN
  244. ASSERT((mod.data # NIL) & ((a >= 0) & (a + 3 <= LEN(mod.data))), 20);
  245. x := ((mod.data[a + 3] * 256 +
  246. (mod.data[a + 2] MOD 256)) * 256 +
  247. (mod.data[a + 1] MOD 256)) * 256 +
  248. (mod.data[a] MOD 256)
  249. END Get;
  250. PROCEDURE CheckDllImports (mod: Module);
  251. VAR i, x, y: INTEGER; name: Name; imp: Module; exp: Export;
  252. PROCEDURE SkipLink;
  253. VAR a: INTEGER;
  254. BEGIN
  255. RNum(a);
  256. WHILE a # 0 DO RNum(a); RNum(a) END
  257. END SkipLink;
  258. BEGIN
  259. R := mod.file.NewReader(R);
  260. R.SetPos(mod.hs + mod.ms + mod.ds + mod.cs);
  261. SkipLink; SkipLink; SkipLink; SkipLink; SkipLink; SkipLink;
  262. i := 0;
  263. WHILE i < mod.ni DO
  264. imp := mod.imp[i];
  265. IF imp # NIL THEN
  266. RNum(x);
  267. WHILE x # 0 DO
  268. ReadName(name); RNum(y);
  269. IF x = mVar THEN
  270. SkipLink;
  271. IF imp.dll THEN
  272. exp := imp.exp;
  273. WHILE (exp # NIL) & (exp.name # name) DO exp := exp.next END;
  274. IF exp = NIL THEN
  275. NEW(exp); exp.name := name$;
  276. exp.next := imp.exp; imp.exp := exp
  277. END
  278. END
  279. ELSIF x = mTyp THEN RNum(y);
  280. IF imp.dll THEN
  281. RNum(y);
  282. IF y # 0 THEN
  283. W.WriteString("type descriptor (");
  284. W.WriteString(imp.name$); W.WriteChar(".");
  285. W.WriteSString(name);
  286. W.WriteString(") imported from DLL in ");
  287. W.WriteString(mod.name$);
  288. W.WriteLn; StdLog.text.Append(StdLog.buf); error := TRUE;
  289. RETURN
  290. END
  291. ELSE SkipLink
  292. END
  293. ELSIF x = mProc THEN
  294. IF imp.dll THEN
  295. SkipLink;
  296. exp := imp.exp;
  297. WHILE (exp # NIL) & (exp.name # name) DO exp := exp.next END;
  298. IF exp = NIL THEN
  299. NEW(exp); exp.name := name$;
  300. exp.next := imp.exp; imp.exp := exp
  301. END
  302. END
  303. END;
  304. RNum(x)
  305. END
  306. END;
  307. INC(i)
  308. END
  309. END CheckDllImports;
  310. PROCEDURE ReadHeaders;
  311. VAR mod, im, t: Module; x, i, pos: INTEGER; impdll: BOOLEAN; name: Name;
  312. BEGIN
  313. ASSERT(isDll, 126);
  314. mod := modList; modList := NIL; numMod := 0;
  315. WHILE mod # NIL DO (* reverse mod list & count modules *)
  316. IF ~mod.dll THEN INC(numMod) END;
  317. t := mod; mod := t.next; t.next := modList; modList := t
  318. END;
  319. IF isStatic THEN
  320. CodeSize :=
  321. 6 + 5 * numMod + 2 (* _init() *)
  322. + 1 + 5 * numMod + 2 (* _fini() *)
  323. ELSE
  324. CodeSize :=
  325. 6 + 5 + 2 (* _init() *)
  326. + 1 + 5 + 2 (* _fini() *)
  327. END;
  328. DataSize := 0; ConSize := 0;
  329. maxCode := 0; numExp := 0;
  330. mod := modList;
  331. WHILE mod # NIL DO
  332. IF ~mod.dll THEN
  333. mod.file := ThisFile(mod.fileName);
  334. IF mod.file # NIL THEN
  335. R := mod.file.NewReader(R); R.SetPos(0);
  336. Read4(x);
  337. IF x = 6F4F4346H THEN
  338. Read4(x);
  339. Read4(mod.hs); Read4(mod.ms); Read4(mod.ds); Read4(mod.cs);
  340. Read4(mod.vs); RNum(mod.ni); ReadName(mod.name); impdll := FALSE;
  341. IF mod.ni > 0 THEN
  342. NEW(mod.imp, mod.ni);
  343. x := 0;
  344. WHILE x < mod.ni DO
  345. ReadName(name);
  346. IF name = "$$" THEN
  347. IF (mod # kernel) & (kernel # NIL) THEN
  348. mod.imp[x] := kernel
  349. ELSE
  350. W.WriteSString("no kernel"); W.WriteLn;
  351. StdLog.text.Append(StdLog.buf); error := TRUE
  352. END
  353. ELSIF name[0] = "$" THEN
  354. StdLog.String(name$);
  355. i := 1;
  356. WHILE name[i] # 0X DO name[i-1] := name[i]; INC(i) END;
  357. name[i-1] := 0X;
  358. IF i # 1 THEN
  359. Strings.Find(name$, ".so", 0, pos);
  360. IF pos = -1 THEN
  361. name[i - 1] := "."; name[i] := "s"; name[i + 1] := "o"; name[i + 2] := 0X
  362. END
  363. END;
  364. StdLog.String(" "); StdLog.String(name$); StdLog.Ln;
  365. impdll := TRUE; im := modList;
  366. WHILE (im # mod) & (im.name # name) DO im := im.next END;
  367. IF (im = NIL) OR ~im.dll THEN
  368. NEW(im); im.next := modList; modList := im;
  369. im.dll := TRUE;
  370. im.name := name$;
  371. dynstrtab.AddName(name, i);
  372. AddNeededIdx(i)
  373. END;
  374. mod.imp[x] := im
  375. ELSE
  376. im := modList;
  377. WHILE (im # mod) & (im.name # name) DO im := im.next END;
  378. IF im # mod THEN
  379. mod.imp[x] := im
  380. ELSE
  381. W.WriteSString(name);
  382. W.WriteString(" not present (imported in ");
  383. W.WriteString(mod.name$); W.WriteChar(")");
  384. W.WriteLn; StdLog.text.Append(StdLog.buf); error := TRUE
  385. END
  386. END;
  387. INC(x)
  388. END
  389. END;
  390. IF impdll & ~error THEN CheckDllImports(mod) END;
  391. mod.ma := ConSize; INC(ConSize, mod.ms + mod.ds);
  392. mod.va := DataSize; INC(DataSize, mod.vs);
  393. mod.ca := CodeSize; INC(CodeSize, mod.cs);
  394. IF mod.cs > maxCode THEN maxCode := mod.cs END
  395. ELSE
  396. W.WriteString(mod.name$); W.WriteString(": wrong file type");
  397. W.WriteLn; StdLog.text.Append(StdLog.buf); error := TRUE
  398. END;
  399. mod.file.Close; mod.file := NIL
  400. ELSE
  401. W.WriteString(mod.name$); W.WriteString(" not found");
  402. W.WriteLn; StdLog.text.Append(StdLog.buf); error := TRUE
  403. END;
  404. last := mod
  405. END;
  406. mod := mod.next
  407. END;
  408. IF ~isStatic & (main = NIL) THEN
  409. W.WriteSString("no main module specified"); W.WriteLn;
  410. StdLog.text.Append(StdLog.buf); error := TRUE
  411. END;
  412. IF DataSize = 0 THEN DataSize := 1 END
  413. END ReadHeaders;
  414. PROCEDURE WriteElfHeader;
  415. BEGIN
  416. ASSERT(Ro.Pos() = 0, 100);
  417. dynstrtab.AddName(soName$, sonameStrIndexVal);
  418. Write4(464C457FH); Write4(00010101H); Write4(0); Write4(0); (* Magic *)
  419. Write2(3); (* ET_DYN e_type Object file type *)
  420. Write2(3); (* EM_386 e_machine Architecture *)
  421. Write4(1); (* EV_CURRENT e_version Object file version *)
  422. Write4(text.memOffset); (* e_entry Entry point virtual address *)
  423. entryPos := Ro.Pos();
  424. Write4(fixup); (* e_phoff Program header table file offset *)
  425. Write4(fixup); (* e_shoff: Section header table file offset *)
  426. Write4(0); (* e_flags Processor-specific flags *)
  427. Write2(elfHeaderSizeVal); (* e_ehsize ELF header size in bytes *)
  428. Write2(phEntrySizeVal); (* e_phentsize Program header table entry size *)
  429. Write2(phNumVal); (* e_phnum Program header table entry count *)
  430. Write2(shEntrySizeVal); (* e_shentsize Section header table entry size *)
  431. Write2(shNumVal); (* e_shnum Section header table entry count *)
  432. Write2(shStrndxVal); (* e_shstrndx Section header string table index *)
  433. ASSERT(Ro.Pos() = elfHeaderSizeVal, 101)
  434. END WriteElfHeader;
  435. PROCEDURE FixupElfHeader;
  436. BEGIN
  437. Ro.SetPos(entryPos);
  438. Write4(phOffsetVal);
  439. Write4(shOffsetVal)
  440. END FixupElfHeader;
  441. PROCEDURE WriteNullSectionHeader;
  442. BEGIN
  443. Write4(0); (* sh_name Section name (string tbl index) *)
  444. Write4(0); (* SHT_NULL sh_type Section type *)
  445. Write4(0); (* sh_flags Section flags *)
  446. Write4(0); (* ELF header + program header table; sh_addr Section virtual addr at execution *)
  447. Write4(0); (* sh_offset Section file offset *)
  448. Write4(0); (* sh_size Section size in bytes *)
  449. Write4(0); (* SHN_UNDEF sh_link Link to another section *)
  450. Write4(0); (* sh_info Additional section information *)
  451. Write4(0); (* sh_addralign Section alignment *)
  452. Write4(0) (* sh_entsize Entry size if section holds table *)
  453. END WriteNullSectionHeader;
  454. PROCEDURE WriteTextSectionHeader;
  455. VAR i: INTEGER;
  456. BEGIN
  457. headerstrtab.AddName(".text", i);
  458. Write4(i); (* sh_name Section name (string tbl index) *)
  459. Write4(1); (* SHT_PROGBITS sh_type Section type *)
  460. Write4(2H + 4H); (* SHF_ALLOC + SHF_EXECINSTR sh_flags Section flags *)
  461. Write4(text.memOffset); (* sh_addr Section virtual addr at execution *)
  462. Write4(text.fileOffset); (* sh_offset Section file offset *)
  463. Write4(text.size); (* sh_size Section size in bytes *)
  464. Write4(0); (* SHN_UNDEF sh_link Link to another section *)
  465. Write4(0); (* sh_info Additional section information *)
  466. Write4(textAlign); (* sh_addralign Section alignment *)
  467. Write4(0) (* sh_entsize Entry size if section holds table *)
  468. END WriteTextSectionHeader;
  469. PROCEDURE WriteRelTextSectionHeader;
  470. VAR i: INTEGER;
  471. BEGIN
  472. headerstrtab.AddName(".rel.text", i);
  473. Write4(i); (* sh_name Section name (string tbl index) *)
  474. Write4(9); (* SHT_REL sh_type Section type *)
  475. Write4(2H); (* SHF_ALLOC sh_flags Section flags *)
  476. Write4(reltext.memOffset); (* sh_addr Section virtual addr at execution *)
  477. Write4(reltext.fileOffset); (* sh_offset Section file offset *)
  478. Write4(reltext.size); (* sh_size Section size in bytes *)
  479. Write4(dynsymIndexVal); (* sh_link Link to another section -> index of the associated symbol table *)
  480. Write4(textIndexVal); (* sh_info Additional section information -> index of the relocated section *)
  481. Write4(relAlign); (* sh_addralign Section alignment *)
  482. Write4(relEntrySizeVal) (* sh_entsize Entry size if section holds table *)
  483. END WriteRelTextSectionHeader;
  484. PROCEDURE WriteRelRodataSectionHeader;
  485. VAR i: INTEGER;
  486. BEGIN
  487. headerstrtab.AddName(".rel.rodata", i);
  488. Write4(i); (* sh_name Section name (string tbl index) *)
  489. Write4(9); (* SHT_REL sh_type Section type *)
  490. Write4(2H); (* SHF_ALLOC sh_flags Section flags *)
  491. Write4(relrodata.memOffset); (* sh_addr Section virtual addr at execution *)
  492. Write4(relrodata.fileOffset); (* sh_offset Section file offset *)
  493. Write4(relrodata.size); (* sh_size Section size in bytes *)
  494. Write4(dynsymIndexVal); (* sh_link Link to another section -> index of the associated symbol table *)
  495. Write4(rodataIndexVal); (* sh_info Additional section information -> index of the relocated section *)
  496. Write4(relAlign); (* sh_addralign Section alignment *)
  497. Write4(relEntrySizeVal) (* sh_entsize Entry size if section holds table *)
  498. END WriteRelRodataSectionHeader;
  499. PROCEDURE WriteRodataSectionHeader;
  500. VAR i: INTEGER;
  501. BEGIN
  502. headerstrtab.AddName(".rodata", i);
  503. Write4(i); (* sh_name Section name (string tbl index) *)
  504. Write4(1); (* SHT_PROGBITS sh_type Section type *)
  505. Write4(2H); (* SHF_ALLOC sh_flags Section flags *)
  506. Write4(rodata.memOffset); (* sh_addr Section virtual addr at execution *)
  507. Write4(rodata.fileOffset); (* sh_offset Section file offset *)
  508. Write4(rodata.size); (* sh_size Section size in bytes *)
  509. Write4(0); (* sh_link Link to another section *)
  510. Write4(0); (* sh_info Additional section information *)
  511. Write4(rodataAlign); (* sh_addralign Section alignment *)
  512. Write4(0) (* sh_entsize Entry size if section holds table *)
  513. END WriteRodataSectionHeader;
  514. PROCEDURE WriteDynsymSectionHeader;
  515. VAR i: INTEGER;
  516. BEGIN
  517. headerstrtab.AddName(".dynsym", i);
  518. Write4(i); (* sh_name Section name (string tbl index) *)
  519. Write4(11); (* SHT_DYNSYM sh_type Section type *)
  520. Write4(2H); (* SHF_ALLOC sh_flags Section flags *)
  521. Write4(dynsym.memOffset); (* sh_addr Section virtual addr at execution *)
  522. Write4(dynsym.fileOffset); (* sh_offset Section file offset *)
  523. Write4(dynsym.size); (* sh_size Section size in bytes *)
  524. Write4(dynstrIndexVal); (* sh_link Link to another section -> index of the associated string table *)
  525. expPos := Ro.Pos();
  526. Write4(fixup); (* sh_info Additional section information -> see docu 4-17 *)
  527. Write4(dynsymAlign); (* sh_addralign Section alignment *)
  528. Write4(dynsymEntrySizeVal) (* sh_entsize Entry size if section holds table *)
  529. END WriteDynsymSectionHeader;
  530. PROCEDURE FixupDynsymSectionHeader;
  531. BEGIN
  532. Ro.SetPos(expPos);
  533. Write4(dynsymInfoVal)
  534. END FixupDynsymSectionHeader;
  535. PROCEDURE WriteDynstrSectionHeader;
  536. VAR i: INTEGER;
  537. BEGIN
  538. headerstrtab.AddName(".dynstr", i);
  539. Write4(i); (* sh_name Section name (string tbl index) *)
  540. Write4(3); (* SHT_STRTAB sh_type Section type *)
  541. Write4(2H); (* SHF_ALLOC sh_flags Section flags *)
  542. Write4(dynstr.memOffset); (* sh_addr Section virtual addr at execution *)
  543. Write4(dynstr.fileOffset); (* sh_offset Section file offset *)
  544. Write4(dynstr.size); (* sh_size Section size in bytes *)
  545. Write4(0); (* SHN_UNDEF sh_link Link to another section *)
  546. Write4(0); (* sh_info Additional section information *)
  547. Write4(dynstrAlign); (* sh_addralign Section alignment *)
  548. Write4(0) (* sh_entsize Entry size if section holds table *)
  549. END WriteDynstrSectionHeader;
  550. PROCEDURE WriteHashSectionHeader;
  551. VAR i: INTEGER;
  552. BEGIN
  553. headerstrtab.AddName(".hash", i);
  554. Write4(i); (* sh_name Section name (string tbl index) *)
  555. Write4(5); (* SHT_HASH sh_type Section type *)
  556. Write4(2H); (* SHF_ALLOC sh_flags Section flags *)
  557. Write4(hash.memOffset); (* sh_addr Section virtual addr at execution *)
  558. Write4(hash.fileOffset); (* sh_offset Section file offset *)
  559. Write4(hash.size); (* sh_size Section size in bytes *)
  560. Write4(dynsymIndexVal); (* sh_link Link to another section *)
  561. Write4(0); (* sh_info Additional section information *)
  562. Write4(hashAlign); (* sh_addralign Section alignment *)
  563. Write4(4H) (* sh_entsize Entry size if section holds table *)
  564. END WriteHashSectionHeader;
  565. PROCEDURE WriteGotSectionHeader;
  566. VAR i: INTEGER;
  567. BEGIN
  568. headerstrtab.AddName(".got", i);
  569. Write4(i); (* sh_name Section name (string tbl index) *)
  570. Write4(1); (* SHT_PROGBITS sh_type Section type *)
  571. Write4(2H + 1H); (* SHF_ALLOC + SHF_WRITE sh_flags Section flags *)
  572. Write4(got.memOffset); (* sh_addr Section virtual addr at execution *)
  573. Write4(got.fileOffset); (* sh_offset Section file offset *)
  574. Write4(got.size); (* sh_size Section size in bytes *)
  575. Write4(0); (* SHN_UNDEF sh_link Link to another section *)
  576. Write4(0); (* sh_info Additional section information *)
  577. Write4(gotAlign); (* sh_addralign Section alignment *)
  578. Write4(gotEntrySizeVal) (* sh_entsize Entry size if section holds table *)
  579. END WriteGotSectionHeader;
  580. PROCEDURE WriteBssSectionHeader;
  581. VAR i: INTEGER;
  582. BEGIN
  583. headerstrtab.AddName(".bss", i);
  584. Write4(i); (* sh_name Section name (string tbl index) *)
  585. Write4(8); (* SHT_NOBITS sh_type Section type *)
  586. Write4(2H + 1H); (* SHF_ALLOC + SHF_WRITE sh_flags Section flags *)
  587. Write4(bss.memOffset); (* sh_addr Section virtual addr at execution *)
  588. Write4(bss.fileOffset); (* sh_offset Section file offset *)
  589. Write4(bss.size); (* sh_size Section size in bytes *)
  590. Write4(0); (* SHN_UNDEF sh_link Link to another section *)
  591. Write4(0); (* sh_info Additional section information *)
  592. Write4(bssAlign); (* sh_addralign Section alignment *)
  593. Write4(0) (* sh_entsize Entry size if section holds table *)
  594. END WriteBssSectionHeader;
  595. PROCEDURE WriteDynamicSectionHeader;
  596. VAR i: INTEGER;
  597. BEGIN
  598. headerstrtab.AddName(".dynamic", i);
  599. Write4(i); (* sh_name Section name (string tbl index) *)
  600. Write4(6); (* SHT_DYNAMIC sh_type Section type *)
  601. Write4(2H); (* SHF_ALLOC sh_flags Section flags *)
  602. Write4(dynamic.memOffset); (* sh_addr Section virtual addr at execution *)
  603. Write4(dynamic.fileOffset); (* sh_offset Section file offset *)
  604. Write4(dynamic.size); (* sh_size Section size in bytes *)
  605. Write4(dynstrIndexVal); (* sh_link Link to another section -> index of the associated symbol table *)
  606. Write4(0); (* sh_info Additional section information *)
  607. Write4(dynamicAlign); (* sh_addralign Section alignment *)
  608. Write4(dynamicEntrySizeVal) (* sh_entsize Entry size if section holds table *)
  609. END WriteDynamicSectionHeader;
  610. PROCEDURE WriteShstrtabSectionHeader;
  611. VAR i: INTEGER;
  612. BEGIN
  613. headerstrtab.AddName(".shstrtab", i);
  614. Write4(i); (* sh_name Section name (string tbl index) *)
  615. Write4(3); (* SHT_STRTAB sh_type Section type *)
  616. Write4(0); (* sh_flags Section flags *)
  617. Write4(0); (* sh_addr Section virtual addr at execution *)
  618. Write4(shstrtab.fileOffset); (* sh_offset Section file offset *)
  619. shstrtabPos := Ro.Pos();
  620. Write4(fixup); (* sh_size Section size in bytes *)
  621. Write4(0); (* SHN_UNDEF sh_link Link to another section *)
  622. Write4(0); (* sh_info Additional section information *)
  623. Write4(shstrtabAlign); (* sh_addralign Section alignment *)
  624. Write4(0) (* sh_entsize Entry size if section holds table *)
  625. END WriteShstrtabSectionHeader;
  626. PROCEDURE FixupShstrtabSectionHeader;
  627. BEGIN
  628. Ro.SetPos(shstrtabPos);
  629. Write4(shstrtab.size)
  630. END FixupShstrtabSectionHeader;
  631. PROCEDURE WriteRelSectionHeaders;
  632. BEGIN
  633. WriteRelTextSectionHeader;
  634. WriteRelRodataSectionHeader
  635. END WriteRelSectionHeaders;
  636. PROCEDURE WriteSectionHeaderTable;
  637. BEGIN
  638. shOffsetVal := Ro.Pos();
  639. WriteNullSectionHeader;
  640. WriteTextSectionHeader;
  641. WriteRodataSectionHeader;
  642. WriteRelSectionHeaders;
  643. WriteDynsymSectionHeader;
  644. WriteDynstrSectionHeader;
  645. WriteHashSectionHeader;
  646. WriteGotSectionHeader;
  647. WriteDynamicSectionHeader;
  648. WriteBssSectionHeader;
  649. WriteShstrtabSectionHeader (* see shStrndxVal *)
  650. (* see shNumVal *)
  651. END WriteSectionHeaderTable;
  652. PROCEDURE FixupSectionHeaderTable;
  653. BEGIN
  654. FixupDynsymSectionHeader;
  655. FixupShstrtabSectionHeader
  656. END FixupSectionHeaderTable;
  657. PROCEDURE WriteTextSegment;
  658. BEGIN
  659. Write4(1); (* PT_LOAD *)
  660. Write4(0); (* offset *)
  661. Write4(0); (* vaddr *)
  662. Write4(0); (* paddr *)
  663. Write4(textSegmentSizeVal); (* file size *)
  664. Write4(textSegmentSizeVal); (* mem size *)
  665. Write4(4H + 1H + 2H); (* flags: R+E+W *)
  666. Write4(pageSize) (* I386 page size *)
  667. END WriteTextSegment;
  668. PROCEDURE WriteDataSegment;
  669. BEGIN
  670. Write4(1); (* PT_LOAD *)
  671. Write4(got.fileOffset); (* offset text segment size *)
  672. Write4(got.memOffset); (* vaddr: offset + alignment * nof pages of text segment *)
  673. Write4(got.memOffset); (* paddr: offset + alignment * nof pages of text segment *)
  674. Write4(dataSegmentSizeVal); (* file size *)
  675. Write4(dataSegmentSizeVal + bss.size); (* mem size -> dataSegmentSizeVal + NOBITS sections *)
  676. Write4(4H + 2H); (* flags: R+W *)
  677. Write4(pageSize) (* I386 page size *)
  678. END WriteDataSegment;
  679. PROCEDURE WriteDynamicSegment;
  680. BEGIN
  681. Write4(2); (* PT_DYNAMIC *)
  682. Write4(dynamic.fileOffset); (* offset text segment size *)
  683. Write4(dynamic.memOffset); (* vaddr: offset of .dynamic section *)
  684. Write4(dynamic.memOffset); (* paddr: vaddr + alignment * nof pages of text segment *)
  685. Write4(dynamicSegmentSizeVal); (* file size *)
  686. Write4(dynamicSegmentSizeVal); (* mem size *)
  687. Write4(4H + 2H); (* flags: R+W *)
  688. Write4(dynamicAlign) (* dynamic section alignement*)
  689. END WriteDynamicSegment;
  690. PROCEDURE WriteProgramHeaderTable;
  691. BEGIN
  692. phOffsetVal := Ro.Pos();
  693. WriteTextSegment; (* .text .rel.text .rodata .dynsym .dynstr .hash *)
  694. WriteDataSegment; (* .got .dynamic .bss *)
  695. WriteDynamicSegment (* .dynamic *)
  696. END WriteProgramHeaderTable;
  697. PROCEDURE SearchObj (mod: Module; VAR name: ARRAY OF SHORTCHAR; m, fp, opt: INTEGER; VAR adr: INTEGER);
  698. VAR dir, len, ntab, f, id, l, r, p, n, i, j: INTEGER; nch, och: SHORTCHAR;
  699. BEGIN
  700. Get(mod, mod.ms + modExports, dir); DEC(dir, rodata.memOffset + mod.ma); Get(mod, dir, len); INC(dir, 4);
  701. Get(mod, mod.ms + modNames, ntab); DEC(ntab, rodata.memOffset + mod.ma);
  702. IF name # "" THEN
  703. l := 0; r := len;
  704. WHILE l < r DO (* binary search *)
  705. n := (l + r) DIV 2; p := dir + n * 16;
  706. Get(mod, p + 8, id);
  707. i := 0; j := ntab + id DIV 256; nch := name[0]; och := SHORT(CHR(mod.data[j]));
  708. WHILE (nch = och) & (nch # 0X) DO INC(i); INC(j); nch := name[i]; och := SHORT(CHR(mod.data[j])) END;
  709. IF och = nch THEN
  710. IF id MOD 16 = m THEN
  711. Get(mod, p, f);
  712. IF m = mTyp THEN
  713. IF ODD(opt) THEN Get(mod, p + 4, f) END;
  714. IF (opt > 1) & (id DIV 16 MOD 16 # mExported) THEN
  715. W.WriteString(mod.name$); W.WriteChar("."); W.WriteSString(name);
  716. W.WriteString(" imported from "); W.WriteString(impg.name$);
  717. W.WriteString(" has wrong visibility"); W.WriteLn; error := TRUE
  718. END;
  719. Get(mod, p + 12, adr)
  720. ELSIF m = mVar THEN
  721. Get(mod, p + 4, adr); INC(adr, bss.memOffset + mod.va)
  722. ELSIF m = mProc THEN
  723. Get(mod, p + 4, adr); INC(adr, text.memOffset + mod.ca)
  724. END;
  725. IF f # fp THEN
  726. W.WriteString(mod.name$); W.WriteChar("."); W.WriteSString(name);
  727. W.WriteString(" imported from "); W.WriteString(impg.name$);
  728. W.WriteString(" has wrong fprint"); W.WriteLn; error := TRUE
  729. END
  730. ELSE
  731. W.WriteString(mod.name$); W.WriteChar("."); W.WriteSString(name);
  732. W.WriteString(" imported from "); W.WriteString(impg.name$);
  733. W.WriteString(" has wrong class"); W.WriteLn; error := TRUE
  734. END;
  735. RETURN
  736. END;
  737. IF och < nch THEN l := n + 1 ELSE r := n END
  738. END;
  739. W.WriteString(mod.name$); W.WriteChar("."); W.WriteSString(name);
  740. W.WriteString(" not found (imported from "); W.WriteString(impg.name$);
  741. W.WriteChar(")"); W.WriteLn; error := TRUE
  742. ELSE (* anonymous type *)
  743. WHILE len > 0 DO
  744. Get(mod, dir + 4, f); Get(mod, dir + 8, id);
  745. IF (f = fp) & (id MOD 16 = mTyp) & (id DIV 256 = 0) THEN
  746. Get(mod, dir + 12, adr); RETURN
  747. END;
  748. DEC(len); INC(dir, 16)
  749. END;
  750. W.WriteString("anonymous type in "); W.WriteString(mod.name$);
  751. W.WriteString(" not found"); W.WriteLn; error := TRUE
  752. END
  753. END SearchObj;
  754. PROCEDURE CollectExports (mod: Module);
  755. VAR dir, len, ntab, id, i, j, n: INTEGER; e, exp: Export;
  756. BEGIN
  757. ASSERT(mod.intf & ~mod.dll, 20);
  758. Get(mod, mod.ms + modExports, dir);
  759. DEC(dir, rodata.memOffset + mod.ma); Get(mod, dir, len); INC(dir, 4);
  760. Get(mod, mod.ms + modNames, ntab); DEC(ntab, rodata.memOffset + mod.ma); n := 0;
  761. WHILE n < len DO
  762. Get(mod, dir + 8, id);
  763. IF (id DIV 16 MOD 16 # mInternal) & (id MOD 16 = mProc) THEN (* exported procedure *)
  764. NEW(exp);
  765. i := 0; j := ntab + id DIV 256;
  766. WHILE mod.data[j] # 0 DO exp.name[i] := SHORT(CHR(mod.data[j])); INC(i); INC(j) END;
  767. exp.name[i] := 0X;
  768. Get(mod, dir + 4, exp.adr);
  769. IF id MOD 16 = mProc THEN
  770. INC(exp.adr, text.memOffset + mod.ca)
  771. ELSE
  772. HALT(126);
  773. ASSERT(id MOD 16 = mVar); INC(exp.adr, bss.memOffset + mod.va)
  774. END;
  775. IF (firstExp = NIL) OR (exp.name < firstExp.name) THEN
  776. exp.next := firstExp; firstExp := exp;
  777. IF lastExp = NIL THEN lastExp := exp END
  778. ELSE
  779. e := firstExp;
  780. WHILE (e.next # NIL) & (exp.name > e.next.name) DO e := e.next END;
  781. exp.next := e.next; e.next := exp;
  782. IF lastExp = e THEN lastExp := exp END
  783. END;
  784. INC(numExp)
  785. END;
  786. INC(n); INC(dir, 16)
  787. END
  788. END CollectExports;
  789. PROCEDURE Relocate0 (link, adr, sym: INTEGER);
  790. CONST
  791. absolute = 100; relative = 101; copy = 102; table = 103; tableend = 104; (* BB fixup types *)
  792. noElfType = MIN(INTEGER);
  793. VAR
  794. offset, linkadr, bbType, elfType, n, x: INTEGER; relText: BOOLEAN;
  795. BEGIN
  796. WHILE link # 0 DO
  797. RNum(offset);
  798. WHILE link # 0 DO
  799. IF link > 0 THEN
  800. n := (code[link] MOD 256) + (code[link+1] MOD 256) * 256 + code[link+2] * 65536;
  801. bbType := code[link+3];
  802. linkadr := text.memOffset + impg.ca + link
  803. ELSE
  804. n := (impg.data[-link] MOD 256) + (impg.data[-link+1] MOD 256) * 256 + impg.data[-link+2] * 65536;
  805. bbType := impg.data[-link+3];
  806. linkadr := rodata.memOffset + impg.ma - link
  807. END;
  808. elfType := noElfType;
  809. IF bbType = absolute THEN
  810. IF sym = noSymbol THEN
  811. x := adr + offset;
  812. elfType := r386Relative
  813. ELSE
  814. x := 0H;
  815. elfType := r38632 + sym * 256
  816. END
  817. ELSIF bbType = relative THEN
  818. IF sym = noSymbol THEN
  819. x := adr + offset - linkadr - 4
  820. ELSE
  821. x := 0FFFFFFFCH;
  822. elfType := r386pc32 + sym * 256
  823. END
  824. ELSIF bbType = copy THEN
  825. Get(impd, adr + offset - rodata.memOffset - impd.ma, x);
  826. IF x # 0 THEN elfType := r386Relative END
  827. ELSIF bbType = table THEN
  828. x := adr + n; n := link + 4;
  829. elfType := r386Relative
  830. ELSIF bbType = tableend THEN
  831. x := adr + n; n := 0;
  832. elfType := r386Relative
  833. ELSE HALT(99)
  834. END;
  835. relText := link > 0;
  836. IF link > 0 THEN
  837. code[link] := SHORT(SHORT(x));
  838. code[link+1] := SHORT(SHORT(x DIV 100H));
  839. code[link+2] := SHORT(SHORT(x DIV 10000H));
  840. code[link+3] := SHORT(SHORT(x DIV 1000000H))
  841. ELSE
  842. link := -link;
  843. impg.data[link] := SHORT(SHORT(x));
  844. impg.data[link+1] := SHORT(SHORT(x DIV 100H));
  845. impg.data[link+2] := SHORT(SHORT(x DIV 10000H));
  846. impg.data[link+3] := SHORT(SHORT(x DIV 1000000H))
  847. END;
  848. IF elfType # noElfType THEN
  849. IF relText THEN
  850. relTextTab.Add(linkadr, elfType)
  851. ELSE
  852. relRodataTab.Add(linkadr, elfType)
  853. END
  854. END;
  855. link := n
  856. END;
  857. RNum(link)
  858. END
  859. END Relocate0;
  860. PROCEDURE Relocate (adr: INTEGER);
  861. VAR link: INTEGER;
  862. BEGIN
  863. RNum(link); Relocate0(link, adr, noSymbol)
  864. END Relocate;
  865. PROCEDURE RelocateSymbol (adr, sym: INTEGER);
  866. VAR link: INTEGER;
  867. BEGIN
  868. RNum(link); Relocate0(link, adr, sym)
  869. END RelocateSymbol;
  870. PROCEDURE SymbolIndex (IN name: Name): INTEGER;
  871. VAR n: INTEGER; exp: Export; m: Module;
  872. BEGIN
  873. n := 0; exp := NIL;
  874. m := modList;
  875. WHILE (m # NIL) & (exp = NIL) DO
  876. IF m.dll THEN
  877. exp := m.exp;
  878. WHILE (exp # NIL) & (exp.name$ # name$) DO
  879. INC(n);
  880. exp := exp.next
  881. END
  882. END;
  883. m := m.next
  884. END;
  885. ASSERT((exp # NIL) & (exp.name$ = name$), 60);
  886. RETURN firstDllSymbolVal + n
  887. END SymbolIndex;
  888. PROCEDURE WriteTextSection;
  889. VAR mod, m: Module; i, x, a, sym, fp, opt: INTEGER; exp: Export; name: Name;
  890. BEGIN
  891. ASSERT(isDll, 126);
  892. ASSERT(~doWrite OR (Ro.Pos() = text.fileOffset), 100);
  893. WriteCh(053X); (* push ebx *) (* _init() *)
  894. a := 1;
  895. WriteCh(0BBX); Write4(rodata.memOffset + last.ma + last.ms); (* mov bx, modlist *)
  896. relTextTab.Add(text.memOffset + a + 1, r386Relative);
  897. INC(a, 5);
  898. IF isStatic THEN
  899. m := modList;
  900. WHILE m # NIL DO
  901. IF ~m.dll THEN
  902. WriteCh(0E8X); INC(a, 5); Write4(m.ca - a) (* call body *)
  903. END;
  904. m := m.next
  905. END
  906. ELSE
  907. WriteCh(0E8X); INC(a, 5); Write4(main.ca - a) (* call main *)
  908. END;
  909. WriteCh(05BX); (* pop ebx *)
  910. WriteCh(0C3X); (* ret *)
  911. INC(a, 2);
  912. finiMemOffsetVal := text.memOffset + a;
  913. WriteCh(053X); (* push ebx *) (* _fini() *)
  914. INC(a);
  915. finiPos := text.memOffset + a;
  916. IF isStatic THEN
  917. i := 0;
  918. WHILE i < numMod DO (* nop for call terminator *)
  919. WriteCh(02DX); Write4(0); (* sub EAX, 0 *)
  920. INC(i); INC(a, 5)
  921. END
  922. ELSE
  923. WriteCh(02DX); Write4(0); (* sub EAX, 0 *)
  924. INC(a, 5)
  925. END;
  926. lastTerm := a;
  927. WriteCh(05BX); (* pop ebx *)
  928. WriteCh(0C3X); (* ret *)
  929. IF ~doWrite THEN NEW(code, maxCode) END;
  930. mod := modList;
  931. WHILE mod # NIL DO
  932. impg := mod;
  933. impd := mod;
  934. IF ~mod.dll THEN
  935. mod.file := ThisFile(mod.fileName);
  936. R := mod.file.NewReader(R);
  937. R.SetPos(mod.hs);
  938. IF ~doWrite THEN NEW(mod.data, mod.ms + mod.ds) END;
  939. R.ReadBytes(mod.data^, 0, mod.ms + mod.ds);
  940. R.ReadBytes(code^, 0, mod.cs);
  941. RNum(x);
  942. IF x # 0 THEN
  943. IF (mod # kernel) & (kernel # NIL) THEN
  944. SearchObj(kernel, newRec, mProc, NewRecFP, 0, a);
  945. IF error THEN RETURN END;
  946. Relocate0(x, a, noSymbol)
  947. ELSE
  948. W.WriteSString("no kernel"); W.WriteLn;
  949. StdLog.text.Append(StdLog.buf);
  950. error := TRUE;
  951. RETURN
  952. END
  953. END;
  954. RNum(x);
  955. IF x # 0 THEN
  956. IF (mod # kernel) & (kernel # NIL) THEN
  957. SearchObj(kernel, newArr, mProc, NewArrFP, 0, a);
  958. IF error THEN RETURN END;
  959. Relocate0(x, a, noSymbol)
  960. ELSE
  961. W.WriteSString("no kernel"); W.WriteLn;
  962. StdLog.text.Append(StdLog.buf); error := TRUE;
  963. RETURN
  964. END
  965. END;
  966. Relocate(rodata.memOffset + mod.ma); (* metalink *)
  967. Relocate(rodata.memOffset + mod.ma + mod.ms); (* desclink *)
  968. Relocate(text.memOffset + mod.ca); (* codelink *)
  969. Relocate(bss.memOffset + mod.va); (* datalink *)
  970. i := 0;
  971. WHILE i < mod.ni DO
  972. m := mod.imp[i]; impd := m; RNum(x);
  973. WHILE x # 0 DO
  974. ReadName(name); RNum(fp); opt := 0;
  975. IF x = mTyp THEN RNum(opt) END;
  976. sym := noSymbol;
  977. IF m.dll THEN
  978. IF (x = mProc) OR (x = mVar) THEN
  979. exp := m.exp;
  980. WHILE exp.name # name DO exp := exp.next END;
  981. a := noAddr;
  982. sym := SymbolIndex(name)
  983. END
  984. ELSE
  985. SearchObj(m, name, x, fp, opt, a);
  986. IF error THEN RETURN END
  987. END;
  988. IF x # mConst THEN
  989. RelocateSymbol(a, sym)
  990. END;
  991. RNum(x)
  992. END;
  993. IF ~m.dll THEN
  994. Get(mod, mod.ms + modImports, x); DEC(x, rodata.memOffset + mod.ma); INC(x, 4 * i);
  995. Put(mod, x, rodata.memOffset + m.ma + m.ms); (* imp ref *)
  996. relRodataTab.Add(rodata.memOffset + mod.ma + x, r386Relative);
  997. Get(m, m.ms + modRefcnt, x); Put(m, m.ms + modRefcnt, x + 1) (* inc ref count *)
  998. END;
  999. INC(i)
  1000. END;
  1001. WriteBytes(code^, 0, mod.cs);
  1002. IF mod.intf THEN CollectExports(mod) END;
  1003. mod.file.Close; mod.file := NIL
  1004. END;
  1005. mod := mod.next
  1006. END;
  1007. ASSERT(~doWrite OR (text.size = Ro.Pos() - text.fileOffset), 101)
  1008. END WriteTextSection;
  1009. PROCEDURE WriteTermCode (m: Module; i: INTEGER);
  1010. VAR x: INTEGER;
  1011. BEGIN
  1012. IF m # NIL THEN
  1013. IF m.dll THEN WriteTermCode(m.next, i)
  1014. ELSE
  1015. IF isStatic THEN WriteTermCode(m.next, i + 1) END;
  1016. Get(m, m.ms + modTerm, x); (* terminator address in mod desc*)
  1017. IF x = 0 THEN
  1018. WriteCh(005X); Write4(0) (* add EAX, 0 (nop) *)
  1019. ELSE
  1020. WriteCh(0E8X); Write4(x - lastTerm + 5 * i - text.memOffset) (* call term *)
  1021. END
  1022. END
  1023. END
  1024. END WriteTermCode;
  1025. PROCEDURE FixupTextSection;
  1026. BEGIN
  1027. ASSERT(isDll, 126);
  1028. Ro.SetPos(finiPos);
  1029. IF isStatic THEN
  1030. WriteTermCode(modList, 0)
  1031. ELSE
  1032. WriteTermCode(main, 0)
  1033. END
  1034. END FixupTextSection;
  1035. PROCEDURE WriteRelSection (IN s: Section; IN t: RelTab);
  1036. VAR i: INTEGER;
  1037. BEGIN
  1038. ASSERT(s.fileOffset = Ro.Pos(), 100);
  1039. i := 0;
  1040. WHILE i # t.cur DO
  1041. Write4(t.tab[i].offset);
  1042. Write4(t.tab[i].type);
  1043. INC(i)
  1044. END;
  1045. ASSERT(s.size = Ro.Pos() - s.fileOffset, 101)
  1046. END WriteRelSection;
  1047. PROCEDURE WriteRelSections;
  1048. BEGIN
  1049. WriteRelSection(reltext, relTextTab);
  1050. WriteRelSection(relrodata, relRodataTab)
  1051. END WriteRelSections;
  1052. PROCEDURE WriteRodataSection;
  1053. VAR mod, lastMod: Module; x: INTEGER;
  1054. BEGIN
  1055. ASSERT(~doWrite OR (rodata.fileOffset = Ro.Pos()), 100);
  1056. mod := modList; lastMod := NIL;
  1057. WHILE mod # NIL DO
  1058. IF ~mod.dll THEN
  1059. IF lastMod # NIL THEN
  1060. Put(mod, mod.ms, rodata.memOffset + lastMod.ma + lastMod.ms); (* mod list *)
  1061. relRodataTab.Add(rodata.memOffset + mod.ma + mod.ms, r386Relative)
  1062. END;
  1063. Get(mod, mod.ms + modOpts, x);
  1064. IF isStatic THEN INC(x, 10000H) END; (* set init bit (16) *)
  1065. IF isDll THEN INC(x, 1000000H) END; (* set dll bit (24) *)
  1066. Put(mod, mod.ms + modOpts, x);
  1067. WriteBytes(mod.data^, 0, mod.ms + mod.ds);
  1068. lastMod := mod
  1069. END;
  1070. mod := mod.next
  1071. END;
  1072. ASSERT(~doWrite OR (rodata.size = Ro.Pos() - rodata.fileOffset), 101)
  1073. END WriteRodataSection;
  1074. PROCEDURE WriteSymbolTableEntry (IN name: ARRAY OF SHORTCHAR; val, size: INTEGER; bind, type: BYTE; shndx: INTEGER);
  1075. VAR i: INTEGER; info: SHORTCHAR;
  1076. BEGIN
  1077. IF name # "" THEN dynstrtab.AddName(name, i)
  1078. ELSE i := 0
  1079. END;
  1080. Write4(i);
  1081. Write4(val);
  1082. Write4(size);
  1083. info := SHORT(CHR(bind * 16 + type));
  1084. WriteCh(info);
  1085. WriteCh(0X); (* Symbol visibility *)
  1086. Write2(shndx)
  1087. END WriteSymbolTableEntry;
  1088. PROCEDURE FixupSymbolTableEntry (val, size: INTEGER; bind, type: BYTE; shndx: INTEGER);
  1089. VAR info: SHORTCHAR;
  1090. BEGIN
  1091. Ro.SetPos(Ro.Pos() + 4); (* skip name *)
  1092. Write4(val);
  1093. Write4(size);
  1094. info := SHORT(CHR(bind * 16 + type));
  1095. WriteCh(info);
  1096. WriteCh(0X); (* Symbol visibility *)
  1097. Write2(shndx)
  1098. END FixupSymbolTableEntry;
  1099. PROCEDURE WriteDynsymSection;
  1100. VAR e: Export; m: Module; i: INTEGER;
  1101. BEGIN
  1102. ASSERT(Ro.Pos() = dynsym.fileOffset, 100);
  1103. WriteSymbolTableEntry("", 0, 0, 0, 0, 0);
  1104. WriteSymbolTableEntry("", text.memOffset, 0, stbLocal, sttSection, 1); (* .text section *)
  1105. WriteSymbolTableEntry("", rodata.memOffset, 0, stbLocal, sttSection, 2); (* .rodata section *)
  1106. WriteSymbolTableEntry("", reltext.memOffset, 0, stbLocal, sttSection, 3); (* .rel.text.section *)
  1107. WriteSymbolTableEntry("", relrodata.memOffset, 0, stbLocal, sttSection, 4); (* .rel.rodata section *)
  1108. WriteSymbolTableEntry("", dynsym.memOffset, 0, stbLocal, sttSection, 5); (* .dynsym section *)
  1109. WriteSymbolTableEntry("", dynstr.memOffset, 0, stbLocal, sttSection, 6); (* .dynstr section *)
  1110. WriteSymbolTableEntry("", hash.memOffset, 0, stbLocal, sttSection, 7); (* .hash section *)
  1111. WriteSymbolTableEntry("", got.memOffset, 0, stbLocal, sttSection, 8); (* .got section *)
  1112. WriteSymbolTableEntry("", dynamic.memOffset, 0, stbLocal, sttSection, 9); (* .dynamic section *)
  1113. WriteSymbolTableEntry("", bss.memOffset, 0, stbLocal, sttSection, 10); (* .bss section *)
  1114. dynsymInfoVal := 11;
  1115. i := dynsymInfoVal;
  1116. WriteSymbolTableEntry("_DYNAMIC", dynamic.memOffset, 0, stbGlobal, sttObject, shnAbs);
  1117. hashtab[i] := "_DYNAMIC";
  1118. INC(i);
  1119. ASSERT(i = firstDllSymbolVal);
  1120. m := modList;
  1121. WHILE m # NIL DO
  1122. IF m.dll THEN
  1123. e := m.exp;
  1124. WHILE e # NIL DO
  1125. WriteSymbolTableEntry(e.name, 0, 0, stbGlobal, sttNotype, shnUnd);
  1126. hashtab[i] := e.name$;
  1127. INC(i);
  1128. e := e.next
  1129. END
  1130. END;
  1131. m := m.next
  1132. END;
  1133. e := firstExp;
  1134. WHILE e # NIL DO
  1135. WriteSymbolTableEntry(e.name, fixup, 0, stbGlobal, sttFunc, textIndexVal);
  1136. hashtab[i] := e.name$; INC(i);
  1137. e := e.next
  1138. END;
  1139. WriteSymbolTableEntry("_GLOBAL_OFFSET_TABLE_", got.memOffset, 0, stbGlobal, sttObject, shnAbs);
  1140. hashtab[i] := "_GLOBAL_OFFSET_TABLE_";
  1141. ASSERT(dynsym.size = Ro.Pos() - dynsym.fileOffset, 101)
  1142. END WriteDynsymSection;
  1143. PROCEDURE FixupDynsymSection;
  1144. VAR e: Export; m: Module;
  1145. BEGIN
  1146. Ro.SetPos(dynsym.fileOffset + dynsymEntrySizeVal * firstDllSymbolVal);
  1147. m := modList;
  1148. WHILE m # NIL DO
  1149. IF m.dll THEN
  1150. e := m.exp;
  1151. WHILE e # NIL DO
  1152. Ro.SetPos(Ro.Pos() + dynsymEntrySizeVal);
  1153. e := e.next
  1154. END
  1155. END;
  1156. m := m.next
  1157. END;
  1158. Ro.SetPos(Ro.Pos() + 4);
  1159. e := firstExp;
  1160. WHILE e # NIL DO
  1161. Write4(e.adr);
  1162. Ro.SetPos(Ro.Pos() + 12);
  1163. e := e.next
  1164. END
  1165. END FixupDynsymSection;
  1166. PROCEDURE WriteStringTable (IN t: Strtab);
  1167. VAR i: INTEGER;
  1168. BEGIN
  1169. i := 0;
  1170. WHILE i # t.cur DO
  1171. WriteCh(t.tab[i]);
  1172. INC(i)
  1173. END
  1174. END WriteStringTable;
  1175. PROCEDURE WriteDynstrSection;
  1176. BEGIN
  1177. ASSERT(Ro.Pos() = dynstr.fileOffset, 100);
  1178. WriteStringTable(dynstrtab);
  1179. ASSERT(dynstr.size = Ro.Pos() - dynstr.fileOffset, 101)
  1180. END WriteDynstrSection;
  1181. PROCEDURE Hash (name: ARRAY OF SHORTCHAR): INTEGER;
  1182. VAR i, h, g: INTEGER;
  1183. BEGIN
  1184. h := 0; i := 0;
  1185. WHILE name[i] # 0X DO
  1186. h := ASH(h, 4) + ORD(name[i]);
  1187. g := ORD(BITS(h) * BITS(0F0000000H));
  1188. IF g # 0 THEN
  1189. h := ORD(BITS(h) / BITS(SHORT((g MOD 100000000L) DIV 1000000H)))
  1190. END;
  1191. h := ORD(BITS(h) * (-BITS(g)));
  1192. INC(i)
  1193. END;
  1194. RETURN h
  1195. END Hash;
  1196. PROCEDURE AddToChain (VAR c: ARRAY OF INTEGER; i, idx: INTEGER);
  1197. VAR k: INTEGER;
  1198. BEGIN
  1199. IF c[i] # 0 THEN
  1200. k := i;
  1201. WHILE c[k] # 0 DO k := c[k] END;
  1202. c[k] := idx
  1203. ELSE
  1204. c[i] := idx
  1205. END
  1206. END AddToChain;
  1207. PROCEDURE WriteHashSection;
  1208. VAR n, i, hi: INTEGER; b, c: POINTER TO ARRAY OF INTEGER;
  1209. BEGIN
  1210. ASSERT(hash.fileOffset = Ro.Pos(), 100);
  1211. n := dynsym.size DIV dynsymEntrySizeVal; (* number of enties in the symbol table *)
  1212. NEW(b, n);
  1213. NEW(c, n);
  1214. i := 0;
  1215. WHILE i # n DO
  1216. c[i] := 0; (* STN_UNDEF *)
  1217. IF hashtab[i] # "" THEN
  1218. hi := Hash(hashtab[i]) MOD n;
  1219. IF b[hi] # 0 THEN (* another word has the same index *)
  1220. AddToChain(c, i, b[hi]) (*c[i] := b[hi]*)
  1221. END;
  1222. b[hi] := i
  1223. END;
  1224. INC(i)
  1225. END;
  1226. Write4(n); (* nbucket *)
  1227. Write4(n); (* nchain *)
  1228. i := 0;
  1229. WHILE i # n DO
  1230. Write4(b[i]);
  1231. INC(i)
  1232. END;
  1233. i := 0;
  1234. WHILE i # n DO
  1235. Write4(c[i]);
  1236. INC(i)
  1237. END;
  1238. ASSERT(hash.size = Ro.Pos() - hash.fileOffset, 101)
  1239. END WriteHashSection;
  1240. PROCEDURE WriteGotSection;
  1241. BEGIN
  1242. ASSERT(got.fileOffset = Ro.Pos(), 100);
  1243. Write4(dynamic.memOffset); (* addr of .dynamic section *)
  1244. Write4(0); (* reserved for ? *)
  1245. Write4(0); (* reserved for ? *)
  1246. ASSERT(got.size = Ro.Pos() - got.fileOffset, 101)
  1247. END WriteGotSection;
  1248. PROCEDURE WriteDynamicSectionEntry (tag, val: INTEGER);
  1249. BEGIN
  1250. Write4(tag);
  1251. Write4(val)
  1252. END WriteDynamicSectionEntry;
  1253. PROCEDURE WriteDynamicSection;
  1254. CONST dtNull = 0; dtNeeded = 1; dtHash = 4; dtStrtab = 5; dtSymtab = 6;
  1255. dtStrsz = 10; dtSyment = 11; dtInit = 12; dtFini = 13; dtSoname = 14; dtRel = 17; dtRelsz = 18; dtRelent = 19;
  1256. dtTextrel = 22;
  1257. VAR i: INTEGER;
  1258. BEGIN
  1259. ASSERT(dynamic.fileOffset = Ro.Pos(), 100);
  1260. WriteDynamicSectionEntry(dtSoname, fixup);
  1261. WriteDynamicSectionEntry(dtFini, fixup);
  1262. WriteDynamicSectionEntry(dtInit, text.memOffset);
  1263. WriteDynamicSectionEntry(dtHash, hash.memOffset);
  1264. WriteDynamicSectionEntry(dtStrtab, dynstr.memOffset);
  1265. WriteDynamicSectionEntry(dtSymtab, dynsym.memOffset);
  1266. WriteDynamicSectionEntry(dtStrsz, dynstr.size);
  1267. WriteDynamicSectionEntry(dtSyment, dynsymEntrySizeVal);
  1268. WriteDynamicSectionEntry(dtRel, reltext.memOffset);
  1269. WriteDynamicSectionEntry(dtRelsz, reltext.size + relrodata.size);
  1270. WriteDynamicSectionEntry(dtRelent, relEntrySizeVal);
  1271. i := 0;
  1272. WHILE neededIdx[i] # 0 DO
  1273. WriteDynamicSectionEntry(dtNeeded, neededIdx[i]);
  1274. INC(i)
  1275. END;
  1276. WriteDynamicSectionEntry(dtTextrel, 0);
  1277. WriteDynamicSectionEntry(dtNull, 0); (* DT_NULL: marks the end *)
  1278. ASSERT(dynamic.size = Ro.Pos() - dynamic.fileOffset, 101)
  1279. END WriteDynamicSection;
  1280. PROCEDURE FixupDynamicSection;
  1281. VAR i: INTEGER;
  1282. BEGIN
  1283. Ro.SetPos(dynamic.fileOffset + 4);
  1284. Write4(sonameStrIndexVal);
  1285. Ro.SetPos(Ro.Pos() + 4);
  1286. Write4(finiMemOffsetVal)
  1287. END FixupDynamicSection;
  1288. PROCEDURE WriteBssSection;
  1289. BEGIN
  1290. (*
  1291. The .bss section does not take space in the file.
  1292. This procedure serves consistency-check purposes.
  1293. *)
  1294. ASSERT(bss.fileOffset = Ro.Pos(), 100)
  1295. END WriteBssSection;
  1296. PROCEDURE WriteShstrtabSection;
  1297. BEGIN
  1298. ASSERT(shstrtab.fileOffset = Ro.Pos(), 100);
  1299. WriteStringTable(headerstrtab);
  1300. shstrtab.size := Ro.Pos() - shstrtab.fileOffset
  1301. END WriteShstrtabSection;
  1302. PROCEDURE GetImpListSize (OUT len: INTEGER; OUT count: INTEGER);
  1303. VAR m: Module; e: Export;
  1304. BEGIN
  1305. len := 0; count := 0;
  1306. m := modList;
  1307. WHILE m # NIL DO
  1308. IF m.dll THEN
  1309. e := m.exp;
  1310. WHILE e # NIL DO
  1311. INC(len, LEN(e.name$) + 1);
  1312. INC(count);
  1313. e := e.next
  1314. END
  1315. END;
  1316. m := m.next
  1317. END
  1318. END GetImpListSize;
  1319. PROCEDURE GetExpListSize (OUT len: INTEGER; OUT count: INTEGER);
  1320. VAR e: Export;
  1321. BEGIN
  1322. count := 0; len := 0;
  1323. e := firstExp;
  1324. WHILE e # NIL DO
  1325. INC(len, LEN(e.name$) + 1);
  1326. INC(count);
  1327. e := e.next
  1328. END
  1329. END GetExpListSize;
  1330. PROCEDURE DynsymSize (init: INTEGER): INTEGER;
  1331. VAR size: INTEGER;
  1332. BEGIN
  1333. size := init;
  1334. INC(size, dynsymEntrySizeVal * 11); (* sections entries *)
  1335. INC(size, dynsymEntrySizeVal); (* _DYNAMIC symbol *)
  1336. INC(size, dynsymEntrySizeVal); (* _GLOBAL_OFFSET_TABLE_ symbol *)
  1337. RETURN size
  1338. END DynsymSize;
  1339. PROCEDURE DynstrSize (init: INTEGER): INTEGER;
  1340. VAR size: INTEGER;
  1341. BEGIN
  1342. size := init + 1;
  1343. INC(size, dynstrtab.cur - 1);
  1344. INC(size, LEN(soName$) + 1); (* library name *)
  1345. INC(size, 9); (* "_DYNAMIC" symbol + 0X *)
  1346. INC(size, 21 + 1); (* "_GLOBAL_OFFSET_TABLE_" symbol + trailing 0X *)
  1347. RETURN size
  1348. END DynstrSize;
  1349. PROCEDURE DynamicSize (init: INTEGER): INTEGER;
  1350. VAR i, size: INTEGER;
  1351. BEGIN
  1352. size := init;
  1353. i := 0;
  1354. WHILE neededIdx[i] # 0 DO
  1355. INC(size, dynamicEntrySizeVal);
  1356. INC(i)
  1357. END;
  1358. RETURN size
  1359. END DynamicSize;
  1360. PROCEDURE CalculateLayout;
  1361. VAR headerSize, impCount, expCount, impLen, expLen: INTEGER;
  1362. BEGIN
  1363. ASSERT(~error, 20);
  1364. headerSize := elfHeaderSizeVal + shEntrySizeVal * shNumVal + phEntrySizeVal * phNumVal;
  1365. text.fileOffset := Aligned(headerSize, textAlign);
  1366. text.memOffset := text.fileOffset;
  1367. text.size := CodeSize;
  1368. rodata.fileOffset := Aligned(text.fileOffset + text.size, rodataAlign);
  1369. rodata.memOffset := rodata.fileOffset;
  1370. rodata.size := ConSize;
  1371. reltext.fileOffset := Aligned(rodata.fileOffset + rodata.size, relAlign);
  1372. reltext.memOffset := reltext.fileOffset;
  1373. doWrite := FALSE;
  1374. WriteTextSection; (* this only calculates the number of text relocations *)
  1375. IF error THEN RETURN END;
  1376. reltext.size := relEntrySizeVal * relTextTab.cur;
  1377. relrodata.fileOffset := reltext.fileOffset + reltext.size;
  1378. relrodata.memOffset := relrodata.fileOffset;
  1379. IF ~error THEN
  1380. WriteRodataSection (* this only calculates the number of data relocations *)
  1381. ELSE
  1382. RETURN
  1383. END;
  1384. relrodata.size := relEntrySizeVal * relRodataTab.cur;
  1385. dynsym.fileOffset := Aligned(relrodata.fileOffset + relrodata.size, dynsymAlign);
  1386. dynsym.memOffset := dynsym.fileOffset;
  1387. GetImpListSize(impLen, impCount);
  1388. GetExpListSize(expLen, expCount);
  1389. dynsym.size := DynsymSize((impCount + expCount) * dynsymEntrySizeVal);
  1390. dynstr.fileOffset := Aligned(dynsym.fileOffset + dynsym.size, dynstrAlign);
  1391. dynstr.memOffset := dynstr.fileOffset;
  1392. dynstr.size := DynstrSize(impLen + expLen);
  1393. hash.fileOffset := Aligned(dynstr.fileOffset + dynstr.size, hashAlign);
  1394. hash.memOffset := hash.fileOffset;
  1395. hash.size := 8 + dynsym.size DIV dynsymEntrySizeVal * 4 * 2;
  1396. got.fileOffset := Aligned(hash.fileOffset + hash.size, gotAlign);
  1397. got.memOffset := Aligned(got.fileOffset, pageSize) + got.fileOffset MOD pageSize;
  1398. got.size := 3 * gotEntrySizeVal;
  1399. dynamic.fileOffset := Aligned(got.fileOffset + got.size, dynamicAlign);
  1400. dynamic.memOffset := got.memOffset + dynamic.fileOffset - got.fileOffset;
  1401. dynamic.size := DynamicSize(13 * dynamicEntrySizeVal);
  1402. bss.fileOffset := Aligned(dynamic.fileOffset + dynamic.size, bssAlign);
  1403. bss.memOffset := dynamic.memOffset + bss.fileOffset - dynamic.fileOffset;
  1404. bss.size := DataSize;
  1405. shstrtab.fileOffset := Aligned(bss.fileOffset, shstrtabAlign);
  1406. shstrtab.size := fixup;
  1407. textSegmentSizeVal := got.fileOffset;
  1408. dataSegmentSizeVal := shstrtab.fileOffset - got.fileOffset;
  1409. dynamicSegmentSizeVal := shstrtab.fileOffset - dynamic.fileOffset;
  1410. relTextTab.cur := 0;
  1411. relRodataTab.cur := 0;
  1412. firstExp := NIL; lastExp := NIL;
  1413. doWrite := TRUE
  1414. END CalculateLayout;
  1415. PROCEDURE WriteOut;
  1416. VAR res: INTEGER;
  1417. BEGIN
  1418. ASSERT(~error, 20);
  1419. Out := Files.dir.New(Files.dir.This(""), Files.ask);
  1420. IF Out # NIL THEN
  1421. Ro := Out.NewWriter(Ro); Ro.SetPos(0);
  1422. CalculateLayout;
  1423. IF ~error THEN WriteElfHeader END;
  1424. IF ~error THEN WriteSectionHeaderTable END;
  1425. IF ~error THEN WriteProgramHeaderTable END;
  1426. IF ~error THEN Align(textAlign); WriteTextSection END;
  1427. IF ~error THEN Align(rodataAlign); WriteRodataSection END;
  1428. IF ~error THEN Align(relAlign); WriteRelSections END;
  1429. IF ~error THEN Align(dynsymAlign); WriteDynsymSection END;
  1430. IF ~error THEN Align(dynstrAlign); WriteDynstrSection END;
  1431. IF ~error THEN Align(hashAlign); WriteHashSection END;
  1432. IF ~error THEN Align(gotAlign); WriteGotSection END;
  1433. IF ~error THEN Align(dynamicAlign); WriteDynamicSection END;
  1434. IF ~error THEN Align(bssAlign); WriteBssSection END;
  1435. IF ~error THEN Align(shstrtabAlign); WriteShstrtabSection END;
  1436. IF ~error THEN FixupElfHeader END;
  1437. IF ~error THEN FixupSectionHeaderTable END;
  1438. IF ~error THEN FixupTextSection END;
  1439. IF ~error THEN FixupDynsymSection END;
  1440. IF ~error THEN FixupDynamicSection END;
  1441. Out.Register(soName$, "so", Files.ask, res);
  1442. IF res # 0 THEN error := TRUE END
  1443. ELSE
  1444. error := TRUE
  1445. END
  1446. END WriteOut;
  1447. PROCEDURE ResetHashtab;
  1448. VAR i: INTEGER;
  1449. BEGIN
  1450. i := 0;
  1451. WHILE i # LEN(hashtab) DO
  1452. hashtab[i] := "";
  1453. INC(i)
  1454. END
  1455. END ResetHashtab;
  1456. PROCEDURE ResetNeededIdx;
  1457. VAR i: INTEGER;
  1458. BEGIN
  1459. i := 0;
  1460. WHILE i # LEN(neededIdx) DO
  1461. neededIdx[i] := 0;
  1462. INC(i)
  1463. END
  1464. END ResetNeededIdx;
  1465. PROCEDURE MakeSoName (VAR name: ARRAY OF CHAR; type: ARRAY OF CHAR);
  1466. VAR i, j: INTEGER; ext: Files.Name; ch: CHAR;
  1467. BEGIN
  1468. ASSERT((type = "") OR (type[0] = "."), 20);
  1469. i := 0;
  1470. WHILE (name[i] # 0X) & (name[i] # ".") DO INC(i) END;
  1471. IF name[i] = "." THEN
  1472. IF name[i + 1] = 0X THEN name[i] := 0X END
  1473. ELSIF i < LEN(name) - (LEN(type$) + 1) THEN
  1474. IF type = "" THEN ext := ".so" ELSE ext := type$ END;
  1475. j := 0; ch := ext[0];
  1476. WHILE ch # 0X DO
  1477. IF (ch >= "A") & (ch <= "Z") THEN
  1478. ch := CHR(ORD(ch) + ORD("a") - ORD("A"))
  1479. END;
  1480. name[i] := ch; INC(i); INC(j); ch := ext[j]
  1481. END;
  1482. name[i] := 0X
  1483. END
  1484. END MakeSoName;
  1485. PROCEDURE ParseExt (IN S: TextMappers.Scanner; OUT ext: Files.Name);
  1486. VAR ch: CHAR; i: INTEGER;
  1487. BEGIN
  1488. ext := "";
  1489. S.rider.ReadPrevChar(ch);
  1490. IF ch = "." THEN
  1491. S.rider.ReadChar(ch);
  1492. i := 0;
  1493. WHILE (ch # 20X) & (ch # 9X) DO
  1494. ext[i] := ch;
  1495. INC(i);
  1496. S.rider.ReadChar(ch)
  1497. END;
  1498. ext[i] := 0X
  1499. ELSIF (ch # 20X) & (ch # 9X) THEN
  1500. W.WriteSString("Invalid character '");W.WriteChar(ch); W.WriteSString("' for file name.");
  1501. W.WriteLn; StdLog.text.Append(StdLog.buf); error := TRUE
  1502. END;
  1503. S.SetPos(S.rider.Pos())
  1504. END ParseExt;
  1505. PROCEDURE ParseModList (S: TextMappers.Scanner; end: INTEGER);
  1506. VAR mod: Module;
  1507. BEGIN
  1508. WHILE (S.start < end) & (S.type = TextMappers.string) DO
  1509. NEW(mod); mod.fileName := S.string$;
  1510. mod.next := modList; modList := mod;
  1511. S.Scan;
  1512. WHILE (S.start < end) & (S.type = TextMappers.char) &
  1513. ((S.char = "*") OR (S.char = "+") OR (S.char = "$") OR (S.char = "#")) DO
  1514. IF S.char = "*" THEN mod.dll := TRUE
  1515. ELSIF S.char = "+" THEN kernel := mod
  1516. ELSIF S.char = "$" THEN main := mod
  1517. ELSE mod.intf := TRUE;
  1518. ASSERT(isDll, 126);
  1519. IF ~isDll THEN
  1520. W.WriteSString("Exports from Exe not possible. Use LinkDll or LinkDynDll.");
  1521. W.WriteLn; StdLog.text.Append(StdLog.buf); error := TRUE
  1522. END
  1523. END;
  1524. S.Scan
  1525. END
  1526. END
  1527. END ParseModList;
  1528. PROCEDURE LinkIt;
  1529. VAR S: TextMappers.Scanner; name, ext: Files.Name; end: INTEGER;
  1530. BEGIN
  1531. doWrite := TRUE;
  1532. headerstrtab.tab[0] := 0X;
  1533. headerstrtab.cur := 1;
  1534. dynstrtab.tab[0] := 0X;
  1535. dynstrtab.cur := 1;
  1536. relTextTab.cur := 0;
  1537. relRodataTab.cur := 0;
  1538. ResetHashtab;
  1539. ResetNeededIdx;
  1540. modList := NIL; kernel := NIL; main := NIL;
  1541. last := NIL; impg := NIL; impd := NIL;
  1542. firstExp := NIL; lastExp := NIL;
  1543. Dialog.ShowStatus("linking");
  1544. error := FALSE; modList := NIL;
  1545. IF DevCommanders.par = NIL THEN RETURN END;
  1546. S.ConnectTo(DevCommanders.par.text);
  1547. S.SetPos(DevCommanders.par.beg);
  1548. end := DevCommanders.par.end;
  1549. DevCommanders.par := NIL;
  1550. W.ConnectTo(StdLog.buf); S.Scan;
  1551. IF S.type = TextMappers.string THEN
  1552. name := S.string$;
  1553. ext := "";
  1554. ParseExt(S, ext); S.Scan;
  1555. IF ~error THEN
  1556. MakeSoName(name, ext);
  1557. IF (S.type = TextMappers.char) & (S.char = ":") THEN S.Scan;
  1558. IF (S.type = TextMappers.char) & (S.char = "=") THEN S.Scan;
  1559. ParseModList(S, end);
  1560. ReadHeaders;
  1561. soName := SHORT(name$);
  1562. IF ~error THEN
  1563. WriteOut
  1564. END;
  1565. IF ~error THEN
  1566. W.WriteString("Library " + name + " written: ");
  1567. W.WriteInt(Out.Length()); W.WriteString(" "); W.WriteInt(text.size)
  1568. END
  1569. ELSE
  1570. error := TRUE;
  1571. W.WriteString(" := missing")
  1572. END
  1573. ELSE
  1574. error := TRUE;
  1575. W.WriteString(" := missing")
  1576. END;
  1577. W.WriteLn; StdLog.text.Append(StdLog.buf)
  1578. END
  1579. END;
  1580. IF error THEN Dialog.ShowStatus("Failed to write library") ELSE Dialog.ShowStatus("Ok") END;
  1581. W.ConnectTo(NIL); S.ConnectTo(NIL);
  1582. modList := NIL; kernel := NIL; main := NIL; firstExp := NIL; lastExp := NIL;
  1583. last := NIL; impg := NIL; impd := NIL; code := NIL
  1584. END LinkIt;
  1585. (*
  1586. exes are not supported
  1587. PROCEDURE Link*;
  1588. BEGIN
  1589. HALT(126);
  1590. isDll := FALSE; isStatic := FALSE;
  1591. LinkIt
  1592. END Link;
  1593. PROCEDURE LinkExe*;
  1594. BEGIN
  1595. HALT(126);
  1596. isDll := FALSE; isStatic := TRUE;
  1597. LinkIt
  1598. END LinkExe;
  1599. *)
  1600. PROCEDURE LinkDll*;
  1601. BEGIN
  1602. isDll := TRUE; isStatic := TRUE;
  1603. LinkIt
  1604. END LinkDll;
  1605. PROCEDURE LinkDynDll*;
  1606. BEGIN
  1607. isDll := TRUE; isStatic := FALSE;
  1608. LinkIt
  1609. END LinkDynDll;
  1610. BEGIN
  1611. newRec := "NewRec"; newArr := "NewArr"
  1612. END DevElfLinker.
  1613. LinTestSo LinTestSo2 LinKernel
  1614. (!)DevElfLinker.LinkDynDll libtestbb.so := LinKernel+$ LinTestSo2 LinTestSo# ~
  1615. (!)DevElfLinker.LinkDll libtestbb.so := LinTestSo2 LinTestSo# ~