LindevElfLinker16.txt 57 KB

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