FoxGenericObjectFile.Mod 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705
  1. MODULE FoxGenericObjectFile; (** AUTHOR "negelef"; PURPOSE "Generic Object File Writer"; *)
  2. IMPORT
  3. StringPool, Streams, Commands, Basic := FoxBasic, Formats := FoxFormats, Sections := FoxSections, IntermediateCode := FoxIntermediateCode,
  4. SyntaxTree := FoxSyntaxTree, BinaryCode := FoxBinaryCode,
  5. FingerPrinter := FoxFingerPrinter, Files, Options, ObjectFile, Diagnostics, SymbolFileFormat := FoxTextualSymbolFile, Strings, KernelLog, D := Debugging;
  6. CONST
  7. Version = 4;
  8. Trace = FALSE;
  9. TraceAliases = FALSE;
  10. WarnDuplicateFingerprints = FALSE;
  11. (* optimizations *)
  12. PatchFixups = TRUE; (* patch all fixups that can be processed during object file generation *)
  13. AliasOnlyExported = FALSE; (* create an alias only for exported sections *)
  14. DetailedStatistics = FALSE;
  15. VAR
  16. statModules, statModulesSize: LONGINT;
  17. statHeaders, statHeadersSize: LONGINT;
  18. TYPE
  19. SectionStat = POINTER TO RECORD
  20. name: ARRAY 64 OF CHAR;
  21. entries: LONGINT;
  22. size: LONGINT;
  23. END;
  24. VAR
  25. statPool : Basic.HashTableInt;
  26. TYPE ObjectFileFormat* = OBJECT (Formats.ObjectFileFormat)
  27. VAR binary: BOOLEAN; mergeSections: BOOLEAN;
  28. PROCEDURE & InitObjectFileFormat;
  29. BEGIN
  30. Init; SetExtension(ObjectFile.DefaultExtension);
  31. END InitObjectFileFormat;
  32. PROCEDURE Export* (module: Formats.GeneratedModule; symbolFileFormat: Formats.SymbolFileFormat): BOOLEAN;
  33. VAR fileName: Files.FileName; file: Files.File; writer: Files.Writer; fingerPrinter: FingerPrinter.FingerPrinter; poolMap: ObjectFile.PoolMap;
  34. PROCEDURE ExportSection (section: IntermediateCode.Section): BOOLEAN;
  35. VAR name: ARRAY 256 OF CHAR; (* debugging *)
  36. BEGIN
  37. (*
  38. IF section.IsExternal() OR (section.symbol # NIL) & (section.symbol.scope # NIL) & (section.symbol.scope.ownerModule # module(Sections.Module).module) THEN
  39. (* nothing to do *)
  40. ELSE
  41. *)
  42. IF section.resolved = NIL THEN
  43. Basic.SegmentedNameToString(section.name, name);
  44. D.String('"section.resolved = NIL" for '); D.String(name); D.Ln;
  45. RETURN FALSE
  46. END;
  47. section.resolved.os.identifier.fingerprint := GetFingerPrint (section, fingerPrinter);
  48. CopyFixups (NIL, section.resolved, section.resolved, 0);
  49. ObjectFile.WriteSection(writer,section.resolved.os,binary, poolMap);
  50. (*
  51. END;
  52. *)
  53. RETURN TRUE
  54. END ExportSection;
  55. PROCEDURE MergeSections (sections: Sections.SectionList): BOOLEAN;
  56. VAR
  57. section, test: Sections.Section;
  58. i, j: LONGINT;
  59. name: ObjectFile.SectionName;
  60. sname: Basic.SegmentedName;
  61. msg: ARRAY 256 OF CHAR;
  62. codeAlign, dataAlign, constAlign: LONGINT;
  63. codeUnit, dataUnit, constUnit: LONGINT;
  64. resolved, codeSection, dataSection, constSection: BinaryCode.Section;
  65. alias: BinaryCode.Alias;
  66. irSection: IntermediateCode.Section;
  67. exported: BOOLEAN;
  68. BEGIN
  69. codeAlign := 0; dataAlign := 0; constAlign := 0;
  70. FOR i := 0 TO sections.Length() - 1 DO
  71. section := sections.GetSection(i);
  72. resolved := section(IntermediateCode.Section).resolved;
  73. IF resolved = NIL THEN RETURN FALSE END;
  74. IF (resolved # NIL) & (resolved.pc # 0) & (~resolved.os.fixed) & (resolved.os.priority = 0) THEN
  75. IF section.type = ObjectFile.Code THEN
  76. codeAlign := CommonAlignment(codeAlign, resolved.os.alignment);
  77. ASSERT((codeUnit=0) OR (codeUnit = resolved.os.unit));
  78. codeUnit := resolved.os.unit;
  79. ELSIF section.type = ObjectFile.Data THEN
  80. dataAlign := CommonAlignment(dataAlign, resolved.os.alignment);
  81. ASSERT((dataUnit=0) OR (dataUnit = resolved.os.unit));
  82. dataUnit := resolved.os.unit;
  83. ELSIF section.type = ObjectFile.Const THEN
  84. constAlign := CommonAlignment(constAlign, resolved.os.alignment);
  85. ASSERT((constUnit=0) OR (constUnit = resolved.os.unit));
  86. constUnit := resolved.os.unit;
  87. END;
  88. END;
  89. END;
  90. IF codeUnit > 0 THEN
  91. sname := module.moduleName;
  92. Basic.AppendToSegmentedName(sname,".@CodeSections");
  93. codeSection := BinaryCode.NewBinarySection(ObjectFile.Code, 0, codeUnit, sname, FALSE, FALSE);
  94. codeSection.SetAlignment(FALSE,codeAlign);
  95. END;
  96. IF dataUnit > 0 THEN
  97. sname := module.moduleName;
  98. Basic.AppendToSegmentedName(sname,".@DataSections");
  99. dataSection := BinaryCode.NewBinarySection(ObjectFile.Data, 0, dataUnit, sname, FALSE, FALSE);
  100. dataSection.SetAlignment(FALSE,dataAlign);
  101. END;
  102. IF constUnit > 0 THEN
  103. sname := module.moduleName;
  104. Basic.AppendToSegmentedName(sname,".@ConstSections");
  105. constSection := BinaryCode.NewBinarySection(ObjectFile.Const, 0, constUnit, sname, FALSE, FALSE);
  106. constSection.SetAlignment(FALSE,constAlign);
  107. END;
  108. (*TRACE(codeAlign, dataAlign, constAlign);*)
  109. (*codeAlign := 0; dataAlign := 0; constAlign := 0;*)
  110. FOR i := 0 TO sections.Length() - 1 DO
  111. section := sections.GetSection(i);
  112. resolved := section(IntermediateCode.Section).resolved;
  113. exported := section(IntermediateCode.Section).exported;
  114. IF (resolved # NIL) & (resolved.pc # 0) & (~resolved.os.fixed) & (resolved.os.priority = 0) THEN
  115. IF section.type = ObjectFile.Code THEN
  116. IF resolved.os.alignment # 0 THEN
  117. codeSection.Align(resolved.os.alignment);
  118. END;
  119. resolved.os.identifier.fingerprint := GetFingerPrint (section, fingerPrinter);
  120. NEW(alias, resolved.os.identifier, codeSection.pc);
  121. IF ~AliasOnlyExported OR exported THEN codeSection.aliasList.AddAlias(alias) END;
  122. section(IntermediateCode.Section).SetAlias(codeSection, codeSection.pc);
  123. codeSection.CopyBits(resolved.os.bits,0, resolved.pc*codeUnit);
  124. ELSIF section.type = ObjectFile.Data THEN
  125. IF resolved.os.alignment # 0 THEN
  126. dataSection.Align(resolved.os.alignment);
  127. END;
  128. resolved.os.identifier.fingerprint := GetFingerPrint (section, fingerPrinter);
  129. NEW(alias, resolved.os.identifier, dataSection.pc);
  130. IF ~AliasOnlyExported OR exported THEN dataSection.aliasList.AddAlias(alias) END;
  131. section(IntermediateCode.Section).SetAlias(dataSection, dataSection.pc);
  132. dataSection.CopyBits(resolved.os.bits,0, resolved.pc*dataUnit );
  133. ELSIF section.type = ObjectFile.Const THEN
  134. IF resolved.os.alignment # 0 THEN
  135. constSection.Align(resolved.os.alignment);
  136. END;
  137. resolved.os.identifier.fingerprint := GetFingerPrint (section, fingerPrinter);
  138. NEW(alias, resolved.os.identifier, constSection.pc);
  139. IF ~AliasOnlyExported OR exported THEN constSection.aliasList.AddAlias(alias) END;
  140. section(IntermediateCode.Section).SetAlias(constSection, constSection.pc);
  141. constSection.CopyBits(resolved.os.bits,0, resolved.pc*constUnit);
  142. END;
  143. END;
  144. END;
  145. FOR i := 0 TO sections.Length() - 1 DO
  146. section := sections.GetSection(i);
  147. resolved := section(IntermediateCode.Section).resolved;
  148. exported := section(IntermediateCode.Section).exported;
  149. IF (section(IntermediateCode.Section).alias # NIL) THEN
  150. CopyFixups(sections, resolved, section(IntermediateCode.Section).alias, section(IntermediateCode.Section).aliasOffset);
  151. ELSE
  152. CopyFixups(sections, resolved, resolved,0);
  153. END;
  154. END;
  155. IF codeSection # NIL THEN
  156. UpdateAliases (codeSection, fingerPrinter);
  157. irSection := IntermediateCode.NewSection(sections, SHORTINT(codeSection.os.type), codeSection.os.identifier.name, NIL, FALSE);
  158. irSection.SetResolved(codeSection);
  159. END;
  160. IF dataSection # NIL THEN
  161. UpdateAliases (dataSection, fingerPrinter);
  162. irSection := IntermediateCode.NewSection(sections, SHORTINT(dataSection.os.type), dataSection.os.identifier.name, NIL, FALSE);
  163. irSection.SetResolved(dataSection);
  164. END;
  165. IF constSection # NIL THEN
  166. UpdateAliases (constSection, fingerPrinter);
  167. irSection := IntermediateCode.NewSection(sections, SHORTINT(constSection.os.type), constSection.os.identifier.name, NIL, FALSE);
  168. irSection.SetResolved(constSection);
  169. END;
  170. RETURN TRUE;
  171. END MergeSections;
  172. PROCEDURE ExportSections (sections: Sections.SectionList): BOOLEAN;
  173. VAR
  174. section, test: Sections.Section;
  175. i, j: LONGINT;
  176. name: ObjectFile.SectionName;
  177. sname: Basic.SegmentedName;
  178. msg: ARRAY 256 OF CHAR;
  179. codeAlign, dataAlign, constAlign: LONGINT;
  180. codeUnit, dataUnit, constUnit: LONGINT;
  181. resolved, codeSection, dataSection, constSection: BinaryCode.Section;
  182. alias: BinaryCode.Alias;
  183. irSection: IntermediateCode.Section;
  184. BEGIN
  185. FOR i := 0 TO sections.Length() - 1 DO
  186. section := sections.GetSection(i);
  187. IF (section(IntermediateCode.Section).resolved # NIL) & (section(IntermediateCode.Section).alias = NIL) THEN
  188. IF ~ExportSection(section(IntermediateCode.Section)) THEN RETURN FALSE END;
  189. IF WarnDuplicateFingerprints & (section(IntermediateCode.Section).resolved.os.identifier.fingerprint # 0) THEN
  190. FOR j := 0 TO i - 1 DO
  191. test := sections.GetSection(j);
  192. IF (test(IntermediateCode.Section).resolved # NIL)
  193. & (test(IntermediateCode.Section).resolved.os.identifier.fingerprint = section(IntermediateCode.Section).resolved.os.identifier.fingerprint) THEN
  194. msg := "duplicate fingerPrints: ";
  195. ObjectFile.SegmentedNameToString(section(IntermediateCode.Section).resolved.os.identifier.name,name);
  196. Strings.Append(msg, name);
  197. Strings.Append(msg, ", ");
  198. ObjectFile.SegmentedNameToString(test(IntermediateCode.Section).resolved.os.identifier.name,name);
  199. Strings.Append(msg, name);
  200. Basic.Warning(diagnostics, module.moduleName,Basic.invalidPosition, msg);
  201. END
  202. END
  203. END
  204. END
  205. END;
  206. RETURN TRUE
  207. END ExportSections;
  208. PROCEDURE MakeStatistics(sections: Sections.SectionList);
  209. VAR i: LONGINT;
  210. section: Sections.Section;
  211. resolved: BinaryCode.Section;
  212. suffix: ARRAY 128 OF CHAR;
  213. index: StringPool.Index;
  214. any: ANY;
  215. sectionStat : SectionStat;
  216. BEGIN
  217. FOR i := 0 TO sections.Length()-1 DO
  218. section := sections.GetSection(i);
  219. resolved := section(IntermediateCode.Section).resolved;
  220. Basic.GetSuffix(section.name, suffix);
  221. IF (suffix[0] = "@") & ((suffix[1] # "c") OR (suffix[2] # "o")) THEN
  222. StringPool.GetIndex(suffix, index);
  223. any := statPool.Get(index);
  224. IF any = NIL THEN
  225. NEW(sectionStat);
  226. COPY(suffix, sectionStat.name);
  227. sectionStat.entries := 0;
  228. sectionStat.size := 0;
  229. statPool.Put(index, sectionStat);
  230. ELSE
  231. sectionStat := any(SectionStat);
  232. END;
  233. INC(sectionStat.entries);
  234. INC(sectionStat.size, resolved.pc);
  235. END;
  236. END;
  237. END MakeStatistics;
  238. PROCEDURE ExportModule (module: Sections.Module): BOOLEAN;
  239. VAR result: BOOLEAN; pos,i: LONGINT;
  240. offers, requires: ObjectFile.NameList;
  241. numImports: LONGINT;
  242. name: ObjectFile.SectionName;
  243. import: SyntaxTree.Import;
  244. BEGIN
  245. pos := writer.Pos();
  246. IF DetailedStatistics THEN
  247. MakeStatistics(module.allSections);
  248. END;
  249. IF mergeSections & ~MergeSections(module.allSections) THEN RETURN FALSE END;
  250. NEW (offers, 1); offers[0] := module.moduleName;
  251. import := module.module.moduleScope.firstImport;
  252. numImports := 0;
  253. WHILE import # NIL DO
  254. IF import.direct THEN INC(numImports) END;
  255. import := import.nextImport;
  256. END;
  257. NEW(requires, numImports);
  258. numImports := 0;
  259. import := module.module.moduleScope.firstImport;
  260. WHILE import # NIL DO
  261. IF import.direct THEN
  262. import.module.GetName(name);
  263. requires[numImports] := name;
  264. INC(numImports);
  265. END;
  266. import := import.nextImport;
  267. END;
  268. WriteHeader(writer,binary,module.allSections, poolMap, offers, requires, fingerPrinter);
  269. INC(statHeaders); INC(statHeadersSize, writer.Pos()-pos);
  270. result := ExportSections (module.allSections);
  271. INC(statModules); INC(statModulesSize, writer.Pos()-pos);
  272. RETURN result
  273. END ExportModule;
  274. BEGIN
  275. IF Trace THEN D.String(">>> export generic object file"); D.Ln END;
  276. IF ~(module IS Sections.Module) THEN
  277. Basic.Error (diagnostics, module.moduleName, Basic.invalidPosition, "generated module format does not match object file format");
  278. RETURN FALSE;
  279. END;
  280. IF path # "" THEN Files.JoinPath (path, module.moduleName, fileName); ELSE COPY (module.moduleName, fileName); END;
  281. Files.JoinExtension (fileName, extension, fileName);
  282. IF Trace THEN D.String(">>> filename: "); D.String(fileName); D.Ln END;
  283. file := Files.New (fileName);
  284. IF file = NIL THEN
  285. Basic.Error(diagnostics, module.moduleName,Basic.invalidPosition, "failed to open object file");
  286. RETURN FALSE;
  287. END;
  288. NEW (fingerPrinter);
  289. Files.OpenWriter (writer, file, 0);
  290. IF ExportModule (module(Sections.Module)) THEN
  291. writer.Update;
  292. Files.Register (file);
  293. RETURN TRUE;
  294. ELSE
  295. RETURN FALSE
  296. END
  297. END Export;
  298. PROCEDURE DefineOptions* (options: Options.Options);
  299. BEGIN
  300. options.Add(0X,"objectFileExtension",Options.String);
  301. options.Add(0X,"textualObjectFile",Options.Flag);
  302. options.Add(0X,"mergeSections",Options.Flag);
  303. END DefineOptions;
  304. PROCEDURE GetOptions* (options: Options.Options);
  305. VAR extension: Files.FileName;
  306. BEGIN
  307. IF options.GetString("objectFileExtension",extension) THEN
  308. SetExtension(extension);
  309. END;
  310. binary := ~options.GetFlag("textualObjectFile");
  311. mergeSections := options.GetFlag("mergeSections");
  312. END GetOptions;
  313. PROCEDURE DefaultSymbolFileFormat(): Formats.SymbolFileFormat;
  314. BEGIN RETURN SymbolFileFormat.Get();
  315. END DefaultSymbolFileFormat;
  316. END ObjectFileFormat;
  317. PROCEDURE GetFingerPrint (section: Sections.Section; fingerPrinter: FingerPrinter.FingerPrinter): LONGINT;
  318. VAR fingerPrint: SyntaxTree.FingerPrint; fp: LONGINT; string: Basic.SectionName;
  319. BEGIN
  320. IF section.fingerprint # 0 THEN
  321. fp := section.fingerprint
  322. ELSIF (section.symbol = NIL) OR (section.symbol.scope = NIL) THEN
  323. fp := 0;
  324. IF (section(IntermediateCode.Section).resolved # NIL) THEN
  325. Basic.SegmentedNameToString(section.name, string);
  326. FingerPrinter.FPString(fp, string)
  327. END
  328. ELSIF fingerPrinter # NIL THEN
  329. fingerPrint := fingerPrinter.SymbolFP (section.symbol);
  330. fp := fingerPrint.shallow;
  331. END;
  332. RETURN fp
  333. END GetFingerPrint;
  334. PROCEDURE CheckAlias(sections: Sections.SectionList; VAR identifier: ObjectFile.Identifier; VAR offset: LONGINT);
  335. VAR section: Sections.Section; alias: BinaryCode.Section;
  336. BEGIN
  337. offset := 0;
  338. IF sections = NIL THEN RETURN END;
  339. section := sections.FindByName(identifier.name);
  340. IF (section # NIL) THEN
  341. alias := section(IntermediateCode.Section).alias;
  342. IF alias # NIL THEN
  343. offset := section(IntermediateCode.Section).aliasOffset;
  344. IF TraceAliases THEN
  345. Basic.WriteSegmentedName(D.Log, identifier.name); D.String(" => ");
  346. Basic.WriteSegmentedName(D.Log, alias.os.identifier.name);
  347. D.Ln;
  348. END;
  349. identifier := alias.os.identifier;
  350. END;
  351. END;
  352. END CheckAlias;
  353. PROCEDURE CopyFixups(sections: Sections.SectionList; from, to: BinaryCode.Section; offset: LONGINT);
  354. VAR fixup: BinaryCode.Fixup; i: INTEGER; index: LONGINT; fixupList: ObjectFile.Fixups; fixups: LONGINT;
  355. name: ObjectFile.SegmentedName; aliasSymbol: ObjectFile.Identifier; alias: Sections.Section; aliasOffset: LONGINT;
  356. PROCEDURE PatchFixup (fixup: BinaryCode.Fixup; fixupOffset, targetOffset: LONGINT);
  357. VAR target, address: ObjectFile.Unit; i,j: LONGINT;
  358. PROCEDURE PatchPattern (CONST pattern: ObjectFile.FixupPattern);
  359. BEGIN
  360. to.os.bits.SetBits (target * to.os.unit + pattern.offset, pattern.bits, address); address := ASH (address, -pattern.bits);
  361. END PatchPattern;
  362. PROCEDURE CheckBits(value: LONGINT; offset: LONGINT);
  363. VAR i, nobits,remainder: LONGINT; minval, maxval: ObjectFile.Unit; name: ObjectFile.SectionName; number: ARRAY 32 OF CHAR;
  364. BEGIN
  365. nobits := 0;
  366. FOR i := 0 TO fixup.patterns-1 DO
  367. INC(nobits,fixup.pattern[i].bits);
  368. END;
  369. remainder := ASH(address,-nobits);
  370. IF (nobits <32) & ((remainder > 0) OR (remainder < -1)) THEN
  371. IF fixup.mode = ObjectFile.Relative THEN (* negative values allowed *)
  372. maxval := ASH(1,nobits-1)-1; minval := -maxval-1
  373. ELSE
  374. minval := 0; maxval := ASH(1,nobits);
  375. END;
  376. ObjectFile.SegmentedNameToString(to.os.identifier.name,name);
  377. Strings.Append(name,":");
  378. Strings.IntToStr(offset,number);
  379. Strings.Append(name,number);
  380. D.String(name); D.String("fixup out of range"); D.Ln;
  381. HALT(100);
  382. END;
  383. END CheckBits;
  384. BEGIN
  385. target := fixupOffset + fixup.offset ;
  386. address := targetOffset + fixup.displacement;
  387. IF fixup.mode = ObjectFile.Relative THEN
  388. DEC(address,target)
  389. END;
  390. address := ASH (address, fixup.scale);
  391. CheckBits(address, fixup.offset);
  392. FOR j := 0 TO fixup.patterns-1 DO PatchPattern(fixup.pattern[j]) END;
  393. END PatchFixup;
  394. BEGIN
  395. fixup := from.fixupList.firstFixup; i := 0; fixups := to.os.fixups; fixupList := to.os.fixup;
  396. WHILE fixup # NIL DO
  397. (*! fingerprint := GetFingerPrint(fixup.symbol, fingerPrinter); *)
  398. aliasSymbol := fixup.symbol;
  399. CheckAlias(sections, aliasSymbol, aliasOffset);
  400. IF PatchFixups & (aliasSymbol.name = to.os.identifier.name) & (fixup.mode = BinaryCode.Relative) THEN
  401. PatchFixup(fixup, offset, aliasOffset);
  402. ELSE
  403. index := ObjectFile.AddFixup(fixups, fixupList, aliasSymbol.name, aliasSymbol.fingerprint, fixup.mode,fixup.scale, fixup.patterns, fixup.pattern);
  404. ObjectFile.AddPatch(fixupList[index].patches, fixupList[index].patch, fixup.displacement+aliasOffset, fixup.offset+offset);
  405. END;
  406. fixup := fixup.nextFixup; INC (i);
  407. END;
  408. ObjectFile.SetFixups(to.os, fixups, fixupList);
  409. from.fixupList.InitFixupList; (* delete the source list *)
  410. END CopyFixups;
  411. PROCEDURE UpdateAliases (section: BinaryCode.Section; fingerPrinter: FingerPrinter.FingerPrinter);
  412. VAR alias: BinaryCode.Alias; i: INTEGER; aliasList: ObjectFile.Aliases; aliases: LONGINT; index: LONGINT;
  413. BEGIN
  414. alias := section.aliasList.firstAlias; i := 0; aliases := 0; aliasList := NIL;
  415. WHILE alias # NIL DO
  416. (*! fingerprint := GetFingerPrint(alias.symbol, fingerPrinter); *)
  417. index := ObjectFile.AddAlias(aliases, aliasList, alias.identifier.name, alias.identifier.fingerprint, alias.offset);
  418. alias := alias.nextAlias; INC (i);
  419. END;
  420. ObjectFile.SetAliases(section.os, aliases, aliasList);
  421. section.aliasList.InitAliasList;
  422. END UpdateAliases;
  423. PROCEDURE Get*(): Formats.ObjectFileFormat;
  424. VAR objectFileFormat: ObjectFileFormat;
  425. BEGIN NEW(objectFileFormat); RETURN objectFileFormat
  426. END Get;
  427. PROCEDURE ReadHeader(reader: Streams.Reader; VAR binary: BOOLEAN; VAR poolMap: ObjectFile.PoolMap; VAR offers, requires: ObjectFile.NameList);
  428. VAR ch: CHAR; string: ARRAY 32 OF CHAR; i,j,pos,size: LONGINT; name: ObjectFile.SectionName;
  429. VAR version: LONGINT
  430. BEGIN
  431. reader.String(string);
  432. binary := string="FoxOFB";
  433. IF ~binary THEN ASSERT(string="FoxOFT") END;
  434. reader.SkipWhitespace;
  435. reader.Char(ch); ASSERT(ch='v');
  436. reader.Int(version,FALSE);
  437. IF version < Version THEN KernelLog.String("warning: old object file encountered, recompile all sources"); KernelLog.Ln END;
  438. reader.Char(ch); ASSERT(ch='.');
  439. IF ~binary THEN reader.SkipWhitespace
  440. ELSE
  441. NEW(poolMap,64);
  442. poolMap.Read(reader);
  443. END;
  444. offers := NIL;
  445. requires := NIL;
  446. IF version >= 4 THEN
  447. IF ~binary THEN
  448. reader.String(string); ObjectFile.ReadNameList(reader, offers, binary, poolMap);
  449. reader.SkipWhitespace;
  450. reader.String(string); ObjectFile.ReadNameList(reader, requires, binary, poolMap);
  451. reader.SkipWhitespace;
  452. ELSE
  453. ObjectFile.ReadNameList(reader, offers, binary, poolMap);
  454. ObjectFile.ReadNameList(reader, requires, binary, poolMap);
  455. END
  456. END;
  457. END ReadHeader;
  458. PROCEDURE WriteHeader(writer: Streams.Writer; binary: BOOLEAN; sections: Sections.SectionList; VAR poolMap: ObjectFile.PoolMap; offers, requires: ObjectFile.NameList; fingerPrinter:FingerPrinter.FingerPrinter);
  459. VAR p1,p2, size,i: LONGINT; section: Sections.Section; fixups: LONGINT; fixupList: ObjectFile.Fixups;
  460. PROCEDURE ProcessSection(section: IntermediateCode.Section);
  461. VAR i: LONGINT; fixup: BinaryCode.Fixup; index: LONGINT; alias: BinaryCode.Alias; name: ARRAY 256 OF CHAR;
  462. BEGIN
  463. IF (section.resolved # NIL) & (section.alias = NIL) THEN
  464. poolMap.PutSegmentedName(section.resolved.os.identifier.name);
  465. (* for those sections that have been already resolved *)
  466. FOR i := 0 TO section.resolved.os.fixups-1 DO
  467. poolMap.PutSegmentedName(section.resolved.os.fixup[i].identifier.name);
  468. END;
  469. FOR i := 0 TO section.resolved.os.aliases-1 DO
  470. poolMap.PutSegmentedName(section.resolved.os.alias[i].identifier.name);
  471. END;
  472. fixup := section.resolved.fixupList.firstFixup; i := 0;
  473. WHILE fixup # NIL DO
  474. poolMap.PutSegmentedName(fixup.symbol.name);
  475. fixup := fixup.nextFixup;
  476. END;
  477. alias:= section.resolved.aliasList.firstAlias; i := 0;
  478. WHILE alias # NIL DO
  479. poolMap.PutSegmentedName(alias.identifier.name);
  480. alias := alias.nextAlias;
  481. END;
  482. END;
  483. END ProcessSection;
  484. PROCEDURE NameList(CONST names: ObjectFile.NameList);
  485. BEGIN
  486. IF names # NIL THEN
  487. FOR i := 0 TO LEN(names)-1 DO
  488. poolMap.PutSegmentedName(names[i]);
  489. END;
  490. END;
  491. END NameList;
  492. BEGIN
  493. IF binary THEN writer.String("FoxOFB");
  494. ELSE writer.String("FoxOFT");
  495. END;
  496. writer.Char(' ');
  497. writer.Char('v'); writer.Int(Version,0); writer.Char(".");
  498. IF ~binary THEN
  499. writer.Ln;
  500. writer.String("offers "); ObjectFile.WriteNameList(writer, offers, binary, poolMap);
  501. writer.String("requires "); ObjectFile.WriteNameList(writer, requires, binary, poolMap);
  502. ELSE
  503. NEW(poolMap,512);
  504. poolMap.BeginWriting(writer);
  505. FOR i := 0 TO sections.Length()-1 DO
  506. section := sections.GetSection(i);
  507. ProcessSection(section(IntermediateCode.Section));
  508. END;
  509. NameList(offers); NameList(requires);
  510. poolMap.EndWriting;
  511. ObjectFile.WriteNameList(writer, offers, binary, poolMap);
  512. ObjectFile.WriteNameList(writer, requires, binary, poolMap);
  513. (*
  514. FOR i := 0 TO fixups-1 DO
  515. D.String("fingerprint: "); Basic.WriteSegmentedName(D.Log, fixupList[i].identifier.name); D.Ln;
  516. END;
  517. *)
  518. END;
  519. END WriteHeader;
  520. PROCEDURE GCD(a,b: LONGINT): LONGINT;
  521. VAR h: LONGINT;
  522. BEGIN
  523. WHILE b # 0 DO
  524. h := a MOD b;
  525. a := b;
  526. b := h;
  527. END;
  528. RETURN a
  529. END GCD;
  530. PROCEDURE SCM(a,b: LONGINT): LONGINT;
  531. BEGIN
  532. RETURN a*b DIV GCD(a,b)
  533. END SCM;
  534. PROCEDURE CommonAlignment(a,b: LONGINT): LONGINT;
  535. BEGIN
  536. (*TRACE(a,b);*)
  537. IF a = 0 THEN RETURN b
  538. ELSIF b = 0 THEN RETURN a
  539. ELSE RETURN SCM(a,b)
  540. END;
  541. END CommonAlignment;
  542. PROCEDURE Show*(context: Commands.Context);
  543. VAR
  544. fileName: Files.FileName; file: Files.File; reader: Files.Reader; writer: Streams.Writer;
  545. section: ObjectFile.Section; binary: BOOLEAN; poolMap, poolMapDummy: ObjectFile.PoolMap;
  546. offers, requires: ObjectFile.NameList;
  547. BEGIN
  548. IF context.arg.GetString(fileName) THEN
  549. file := Files.Old(fileName);
  550. IF file # NIL THEN
  551. NEW(reader,file,0);
  552. writer := Basic.GetWriter(Basic.GetDebugWriter(fileName));
  553. ReadHeader(reader, binary, poolMap, offers, requires);
  554. WriteHeader(writer, FALSE, NIL, poolMapDummy, offers, requires, NIL);
  555. WHILE reader.Peek () # 0X DO
  556. ObjectFile.ReadSection (reader, section,binary, poolMap);
  557. ObjectFile.WriteSection(writer, section, FALSE, NIL); (* textual *)
  558. reader.SkipWhitespace;
  559. END;
  560. writer.Update;
  561. ELSE
  562. context.error.String("file not found "); context.error.String(fileName); context.error.Ln
  563. END;
  564. ELSE
  565. context.error.String("no file specificed"); context.error.Ln
  566. END;
  567. END Show;
  568. PROCEDURE MakeLibrary*(context: Commands.Context);
  569. VAR
  570. fileName: Files.FileName; file: Files.File; reader: Files.Reader; (*writer: Streams.Writer;*)
  571. binary: BOOLEAN; poolMap, poolMapDummy: ObjectFile.PoolMap;
  572. bs: BinaryCode.Section;
  573. is: IntermediateCode.Section;
  574. sectionList: Sections.SectionList;
  575. section: ObjectFile.Section;
  576. i: LONGINT;
  577. dest: Files.FileName;
  578. writer: Files.Writer;
  579. name: ObjectFile.SegmentedName;
  580. version: LONGINT;
  581. offers, requires: ObjectFile.NameList;
  582. BEGIN
  583. NEW(sectionList);
  584. IF context.arg.GetString(dest) THEN
  585. (*writer := Basic.GetWriter(Basic.GetDebugWriter(fileName));*)
  586. WHILE context.arg.GetString(fileName) DO
  587. file := Files.Old(fileName);
  588. IF file # NIL THEN
  589. NEW(reader,file,0);
  590. ReadHeader(reader, binary, poolMap,offers, requires);
  591. WHILE reader.Peek () # 0X DO
  592. ObjectFile.InitSection(section);
  593. ObjectFile.ReadSection (reader, section, binary, poolMap);
  594. NEW(bs, SHORTINT(section.type) ,section.priority,section.unit,name, FALSE, FALSE);
  595. bs.os := section;
  596. NEW(is, SHORTINT(bs.os.type), SHORTINT(bs.os.priority), bs.os.identifier.name,NIL, FALSE);
  597. is.SetResolved(bs);
  598. sectionList.AddSection(is);
  599. reader.SkipWhitespace;
  600. END;
  601. ELSE
  602. context.error.String("file not found "); context.error.String(fileName); context.error.Ln;
  603. RETURN;
  604. END;
  605. END;
  606. file := Files.New(dest);
  607. Files.OpenWriter(writer, file, 0);
  608. WriteHeader(writer, TRUE, sectionList, poolMapDummy, NIL, NIL, NIL);
  609. FOR i := 0 TO sectionList.Length()-1 DO
  610. is := sectionList.GetSection(i)(IntermediateCode.Section);
  611. ObjectFile.WriteSection(writer, is.resolved.os, TRUE, poolMapDummy); (* binary *)
  612. END;
  613. writer.Update;
  614. Files.Register(file);
  615. context.out.String("Created library "); context.out.String(dest); context.out.Ln;
  616. END;
  617. END MakeLibrary;
  618. PROCEDURE Statistics*;
  619. VAR iterator: Basic.IntIterator; stat: SectionStat; index: StringPool.Index; any: ANY;
  620. BEGIN
  621. IF DetailedStatistics THEN
  622. iterator := statPool.GetIterator();
  623. WHILE iterator.GetNext(index, any) DO
  624. stat := any(SectionStat);
  625. TRACE(stat.name, stat.entries, stat.size);
  626. END;
  627. END;
  628. TRACE(statModules, statModulesSize);
  629. TRACE(statHeaders, statHeadersSize);
  630. ObjectFile.Statistics;
  631. END Statistics;
  632. PROCEDURE ResetStatistics*;
  633. BEGIN
  634. ObjectFile.ResetStatistics;
  635. statModules := 0; statModulesSize := 0;
  636. statHeaders := 0; statHeadersSize := 0;
  637. IF DetailedStatistics THEN
  638. NEW(statPool,64);
  639. END;
  640. END ResetStatistics;
  641. BEGIN
  642. ResetStatistics
  643. END FoxGenericObjectFile.