2
0

ElfLinker16.txt 57 KB

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