omfbase.pas 50 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400
  1. {
  2. Copyright (c) 2015 by Nikolay Nikolov
  3. Contains Relocatable Object Module Format (OMF) definitions
  4. This is the object format used on the i8086-msdos platform.
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to the Free Software
  15. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  16. ****************************************************************************
  17. }
  18. unit omfbase;
  19. {$i fpcdefs.inc}
  20. interface
  21. {$H+}
  22. uses
  23. cclasses,
  24. owbase;
  25. const
  26. { OMF record types }
  27. RT_THEADR = $80; { Translator Header Record }
  28. RT_LHEADR = $82; { Library Module Header Record }
  29. RT_COMENT = $88; { Comment Record }
  30. RT_MODEND = $8A; { Module End Record }
  31. RT_MODEND32 = $8B;
  32. RT_EXTDEF = $8C; { External Names Definition Record }
  33. RT_PUBDEF = $90; { Public Names Definition Record }
  34. RT_PUBDEF32 = $91;
  35. RT_LINNUM = $94; { Line Numbers Record }
  36. RT_LINNUM32 = $95;
  37. RT_LNAMES = $96; { List of Names Record }
  38. RT_SEGDEF = $98; { Segment Definition Record }
  39. RT_SEGDEF32 = $99;
  40. RT_GRPDEF = $9A; { Group Definition Record }
  41. RT_FIXUPP = $9C; { Fixup Record }
  42. RT_FIXUPP32 = $9D;
  43. RT_LEDATA = $A0; { Logical Enumerated Data Record }
  44. RT_LEDATA32 = $A1;
  45. RT_LIDATA = $A2; { Logical Iterated Data Record }
  46. RT_LIDATA32 = $A3;
  47. RT_COMDEF = $B0; { Communal Names Definition Record }
  48. RT_BAKPAT = $B2; { Backpatch Record }
  49. RT_BAKPAT32 = $B3;
  50. RT_LEXTDEF = $B4; { Local External Names Definition Record }
  51. RT_LEXTDEF32 = $B5;
  52. RT_LPUBDEF = $B6; { Local Public Names Definition Record }
  53. RT_LPUBDEF32 = $B7;
  54. RT_LCOMDEF = $B8; { Local Communal Names Definition Record }
  55. RT_CEXTDEF = $BC; { COMDAT External Names Definition Record }
  56. RT_COMDAT = $C2; { Initialized Communal Data Record }
  57. RT_COMDAT32 = $C3;
  58. RT_LINSYM = $C4; { Symbol Line Numbers Record }
  59. RT_LINSYM32 = $C5;
  60. RT_ALIAS = $C6; { Alias Definition Record }
  61. RT_NBKPAT = $C8; { Named Backpatch Record }
  62. RT_NBKPAT32 = $C9;
  63. RT_LLNAMES = $CA; { Local Logical Names Definition Record }
  64. RT_VERNUM = $CC; { OMF Version Number Record }
  65. RT_VENDEXT = $CE; { Vendor-specific OMF Extension Record }
  66. { OMF comment class }
  67. CC_Translator = $00; { language translator (compiler or assembler) name }
  68. CC_IntelCopyright = $01;
  69. CC_IntelReservedRangeStart = $02;
  70. CC_IntelReservedRangeEnd = $9B;
  71. CC_LibrarySpecifierObsolete = $81;
  72. CC_MsDosVersionObsolete = $9C;
  73. CC_MemoryModel = $9D;
  74. CC_DOSSEG = $9E;
  75. CC_DefaultLibrarySearchName = $9F;
  76. CC_OmfExtension = $A0;
  77. CC_NewOmfExtension = $A1;
  78. CC_LinkPassSeparator = $A2;
  79. CC_LIBMOD = $A3;
  80. CC_EXESTR = $A4;
  81. CC_INCERR = $A6;
  82. CC_NOPAD = $A7;
  83. CC_WKEXT = $A8;
  84. CC_LZEXT = $A9;
  85. CC_Comment = $DA;
  86. CC_Compiler = $DB;
  87. CC_Date = $DC;
  88. CC_Timestamp = $DD;
  89. CC_User = $DF;
  90. CC_DependencyFileBorland = $E9;
  91. CC_CommandLineMicrosoft = $FF;
  92. type
  93. TOmfSegmentAlignment = (
  94. saAbsolute = 0,
  95. saRelocatableByteAligned = 1,
  96. saRelocatableWordAligned = 2,
  97. saRelocatableParaAligned = 3,
  98. saRelocatablePageAligned = 4, { 32-bit linkers extension }
  99. saRelocatableDWordAligned = 5, { 32-bit linkers extension }
  100. saNotSupported = 6,
  101. saNotDefined = 7);
  102. TOmfSegmentCombination = (
  103. scPrivate = 0,
  104. scReserved1 = 1,
  105. scPublic = 2,
  106. scReserved3 = 3,
  107. scPublic4 = 4, { same as scPublic }
  108. scStack = 5,
  109. scCommon = 6,
  110. scPublic7 = 7); { same as scPublic }
  111. TOmfSegmentUse = (suUse16, suUse32);
  112. TOmfFixupThread = (ftThread0, ftThread1, ftThread2, ftThread3);
  113. TOmfFixupMode = (fmSelfRelative, fmSegmentRelative);
  114. TOmfFixupLocationType = (
  115. fltLoByte = 0, { low 8 bits of 16-bit offset }
  116. fltOffset = 1, { 16-bit offset }
  117. fltBase = 2, { 16-bit base (segment) }
  118. fltFarPointer = 3, { 16-bit base:16-bit offset }
  119. fltHiByte = 4, { high 8 bits of 16-bit offset }
  120. fltLoaderResolvedOffset = 5, { PharLap: Offset32 }
  121. fltUndefined6 = 6, { PharLap: Pointer48 }
  122. fltUndefined7 = 7,
  123. fltUndefined8 = 8,
  124. fltOffset32 = 9, { 32-bit offset }
  125. fltUndefined10 = 10,
  126. fltFarPointer48 = 11, { 16-bit base:32-bit offset }
  127. fltUndefined12 = 12,
  128. fltLoaderResolvedOffset32 = 13,
  129. fltUndefined14 = 14,
  130. fltUndefined15 = 15);
  131. TOmfFixupFrameMethod = (
  132. ffmSegmentIndex = 0, { SI(<segment name>) - The frame is the canonic frame of the logical
  133. segment segment defined by the index }
  134. ffmGroupIndex = 1, { GI(<group name>) - The frame is the canonic frame of the group
  135. (= the canonic frame of the logical segment from the group,
  136. located at the lowest memory address) }
  137. ffmExternalIndex = 2, { EI(<symbol name>) - The frame is determined depending on the external's public definition:
  138. * if the symbol is defined relative to a logical segment and no defined group,
  139. the frame of the logical segment is used
  140. * if the symbol is defined absolutely, without reference to a logical segment and
  141. no defined group, the FRAME NUMBER from the symbol's PUBDEF record is used
  142. * regardless of how the symbol is specified, if there's an associated group,
  143. that group's canonic frame is used }
  144. ffmFrameNumber = 3, { <FRAME NUMBER> - The frame is a directly specified constant. }
  145. ffmLocation = 4, { LOCATION - The frame is determined by the location (i.e. the canonic frame of the logical
  146. segment where the fixup location is) }
  147. ffmTarget = 5, { TARGET - The frame is determined by the target. }
  148. ffmNone = 6, { NONE - There is no frame. Used for 8089 self-relative references. }
  149. ffmUndefined = 7);
  150. TOmfFixupTargetMethod = (
  151. ftmSegmentIndex = 0, { SI(<segment name>),<displacement> }
  152. ftmGroupIndex = 1, { GI(<group name>),<displacement> }
  153. ftmExternalIndex = 2, { EI(<symbol name>),<displacement> }
  154. ftmFrameNumber = 3, { <FRAME NUMBER>,<displacement> }
  155. ftmSegmentIndexNoDisp = 4, { SI(<segment name>) }
  156. ftmGroupIndexNoDisp = 5, { GI(<group name>) }
  157. ftmExternalIndexNoDisp = 6, { EI(<symbol name>) }
  158. ftmFrameNumberNoDisp = 7); { <FRAME NUMBER> }
  159. { TOmfOrderedNameCollection }
  160. TOmfOrderedNameCollection = class
  161. private
  162. FStringList: array of string;
  163. function GetCount: Integer;
  164. function GetString(Index: Integer): string;
  165. procedure SetString(Index: Integer; AValue: string);
  166. public
  167. function Add(const S: string): Integer;
  168. procedure Clear;
  169. property Strings [Index: Integer]: string read GetString write SetString; default;
  170. property Count: Integer read GetCount;
  171. end;
  172. { TOmfRawRecord }
  173. TOmfRawRecord = class
  174. private
  175. function GetChecksumByte: Byte;
  176. function GetRecordLength: Word;
  177. function GetRecordType: Byte;
  178. procedure SetChecksumByte(AValue: Byte);
  179. procedure SetRecordLength(AValue: Word);
  180. procedure SetRecordType(AValue: Byte);
  181. public
  182. RawData: array [-3..65535] of Byte;
  183. property RecordType: Byte read GetRecordType write SetRecordType;
  184. property RecordLength: Word read GetRecordLength write SetRecordLength;
  185. function ReadStringAt(Offset: Integer; out s: string): Integer;
  186. function WriteStringAt(Offset: Integer; s: string): Integer;
  187. function ReadIndexedRef(Offset: Integer; out IndexedRef: Integer): Integer;
  188. function WriteIndexedRef(Offset: Integer; IndexedRef: Integer): Integer;
  189. procedure CalculateChecksumByte;
  190. function VerifyChecksumByte: boolean;
  191. property ChecksumByte: Byte read GetChecksumByte write SetChecksumByte;
  192. procedure ReadFrom(aReader: TObjectReader);
  193. procedure WriteTo(aWriter: TObjectWriter);
  194. end;
  195. { TOmfParsedRecord }
  196. TOmfParsedRecord = class
  197. public
  198. procedure DecodeFrom(RawRecord: TOmfRawRecord);virtual;abstract;
  199. procedure EncodeTo(RawRecord: TOmfRawRecord);virtual;abstract;
  200. end;
  201. { TOmfRecord_THEADR }
  202. TOmfRecord_THEADR = class(TOmfParsedRecord)
  203. private
  204. FModuleName: string;
  205. public
  206. procedure DecodeFrom(RawRecord: TOmfRawRecord);override;
  207. procedure EncodeTo(RawRecord: TOmfRawRecord);override;
  208. property ModuleName: string read FModuleName write FModuleName;
  209. end;
  210. { TOmfRecord_COMENT }
  211. TOmfRecord_COMENT = class(TOmfParsedRecord)
  212. private
  213. FCommentType: Byte;
  214. FCommentClass: Byte;
  215. FCommentString: string;
  216. function GetNoList: Boolean;
  217. function GetNoPurge: Boolean;
  218. procedure SetNoList(AValue: Boolean);
  219. procedure SetNoPurge(AValue: Boolean);
  220. public
  221. procedure DecodeFrom(RawRecord: TOmfRawRecord);override;
  222. procedure EncodeTo(RawRecord: TOmfRawRecord);override;
  223. property CommentType: Byte read FCommentType write FCommentType;
  224. property CommentClass: Byte read FCommentClass write FCommentClass;
  225. property CommentString: string read FCommentString write FCommentString;
  226. property NoPurge: Boolean read GetNoPurge write SetNoPurge;
  227. property NoList: Boolean read GetNoList write SetNoList;
  228. end;
  229. { TOmfRecord_LNAMES }
  230. TOmfRecord_LNAMES = class(TOmfParsedRecord)
  231. private
  232. FNames: TOmfOrderedNameCollection;
  233. FNextIndex: Integer;
  234. public
  235. constructor Create;
  236. procedure DecodeFrom(RawRecord: TOmfRawRecord);override;
  237. procedure EncodeTo(RawRecord: TOmfRawRecord);override;
  238. property Names: TOmfOrderedNameCollection read FNames write FNames;
  239. property NextIndex: Integer read FNextIndex write FNextIndex;
  240. end;
  241. { TOmfRecord_SEGDEF }
  242. TOmfRecord_SEGDEF = class(TOmfParsedRecord)
  243. private
  244. FAlignment: TOmfSegmentAlignment;
  245. FCombination: TOmfSegmentCombination;
  246. FUse: TOmfSegmentUse;
  247. FFrameNumber: Word;
  248. FOffset: Byte;
  249. FIs32Bit: Boolean;
  250. FSegmentLength: Int64; { int64, because it can be 2**32 }
  251. FSegmentNameIndex: Integer;
  252. FClassNameIndex: Integer;
  253. FOverlayNameIndex: Integer;
  254. public
  255. procedure DecodeFrom(RawRecord: TOmfRawRecord);override;
  256. procedure EncodeTo(RawRecord: TOmfRawRecord);override;
  257. property Alignment: TOmfSegmentAlignment read FAlignment write FAlignment;
  258. property Combination: TOmfSegmentCombination read FCombination write FCombination;
  259. property Use: TOmfSegmentUse read FUse write FUse;
  260. property FrameNumber: Word read FFrameNumber write FFrameNumber;
  261. property Offset: Byte read FOffset write FOffset;
  262. property Is32Bit: Boolean read FIs32Bit write FIs32Bit;
  263. property SegmentLength: Int64 read FSegmentLength write FSegmentLength;
  264. property SegmentNameIndex: Integer read FSegmentNameIndex write FSegmentNameIndex;
  265. property ClassNameIndex: Integer read FClassNameIndex write FClassNameIndex;
  266. property OverlayNameIndex: Integer read FOverlayNameIndex write FOverlayNameIndex;
  267. end;
  268. TSegmentList = array of Integer;
  269. { TOmfRecord_GRPDEF }
  270. TOmfRecord_GRPDEF = class(TOmfParsedRecord)
  271. private
  272. FGroupNameIndex: Integer;
  273. FSegmentList: TSegmentList;
  274. public
  275. procedure DecodeFrom(RawRecord: TOmfRawRecord);override;
  276. procedure EncodeTo(RawRecord: TOmfRawRecord);override;
  277. property GroupNameIndex: Integer read FGroupNameIndex write FGroupNameIndex;
  278. property SegmentList: TSegmentList read FSegmentList write FSegmentList;
  279. end;
  280. { TOmfPublicNameElement }
  281. TOmfPublicNameElement = class(TFPHashObject)
  282. private
  283. FPublicOffset: DWord;
  284. FTypeIndex: Integer;
  285. public
  286. function GetLengthInFile(Is32Bit: Boolean): Integer;
  287. property PublicOffset: DWord read FPublicOffset write FPublicOffset;
  288. property TypeIndex: Integer read FTypeIndex write FTypeIndex;
  289. end;
  290. { TOmfRecord_PUBDEF }
  291. TOmfRecord_PUBDEF = class(TOmfParsedRecord)
  292. private
  293. FIs32Bit: Boolean;
  294. FBaseGroupIndex: Integer;
  295. FBaseSegmentIndex: Integer;
  296. FBaseFrame: Word;
  297. FPublicNames: TFPHashObjectList;
  298. FNextIndex: Integer;
  299. public
  300. procedure DecodeFrom(RawRecord: TOmfRawRecord);override;
  301. procedure EncodeTo(RawRecord: TOmfRawRecord);override;
  302. property Is32Bit: Boolean read FIs32Bit write FIs32Bit;
  303. property BaseGroupIndex: Integer read FBaseGroupIndex write FBaseGroupIndex;
  304. property BaseSegmentIndex: Integer read FBaseSegmentIndex write FBaseSegmentIndex;
  305. property BaseFrame: Word read FBaseFrame write FBaseFrame;
  306. property PublicNames: TFPHashObjectList read FPublicNames write FPublicNames;
  307. property NextIndex: Integer read FNextIndex write FNextIndex;
  308. end;
  309. { TOmfExternalNameElement }
  310. TOmfExternalNameElement = class(TFPHashObject)
  311. private
  312. FTypeIndex: Integer;
  313. public
  314. function GetLengthInFile: Integer;
  315. property TypeIndex: Integer read FTypeIndex write FTypeIndex;
  316. end;
  317. { TOmfRecord_EXTDEF }
  318. TOmfRecord_EXTDEF = class(TOmfParsedRecord)
  319. private
  320. FExternalNames: TFPHashObjectList;
  321. FNextIndex: Integer;
  322. public
  323. procedure DecodeFrom(RawRecord: TOmfRawRecord);override;
  324. procedure EncodeTo(RawRecord: TOmfRawRecord);override;
  325. property ExternalNames: TFPHashObjectList read FExternalNames write FExternalNames;
  326. property NextIndex: Integer read FNextIndex write FNextIndex;
  327. end;
  328. { TOmfRecord_MODEND }
  329. TOmfRecord_MODEND = class(TOmfParsedRecord)
  330. private
  331. FIs32Bit: Boolean;
  332. FIsMainModule: Boolean;
  333. FHasStartAddress: Boolean;
  334. FSegmentBit: Boolean;
  335. FLogicalStartAddress: Boolean;
  336. FFrameMethod: TOmfFixupFrameMethod;
  337. FFrameDatum: Integer;
  338. FTargetMethod: TOmfFixupTargetMethod;
  339. FTargetDatum: Integer;
  340. FTargetDisplacement: DWord;
  341. FPhysFrameNumber: Word;
  342. FPhysOffset: DWord;
  343. public
  344. procedure DecodeFrom(RawRecord: TOmfRawRecord);override;
  345. procedure EncodeTo(RawRecord: TOmfRawRecord);override;
  346. property Is32Bit: Boolean read FIs32Bit write FIs32Bit;
  347. property IsMainModule: Boolean read FIsMainModule write FIsMainModule;
  348. property HasStartAddress: Boolean read FHasStartAddress write FHasStartAddress;
  349. property SegmentBit: Boolean read FSegmentBit write FSegmentBit;
  350. property LogicalStartAddress: Boolean read FLogicalStartAddress write FLogicalStartAddress;
  351. { properties, specifying a logical start address (used when LogicalStartAddress=true) }
  352. property FrameMethod: TOmfFixupFrameMethod read FFrameMethod write FFrameMethod;
  353. property FrameDatum: Integer read FFrameDatum write FFrameDatum;
  354. property TargetMethod: TOmfFixupTargetMethod read FTargetMethod write FTargetMethod;
  355. property TargetDatum: Integer read FTargetDatum write FTargetDatum;
  356. property TargetDisplacement: DWord read FTargetDisplacement write FTargetDisplacement;
  357. { properties, specifying a physical start address (used when LogicalStartAddress=false) }
  358. property PhysFrameNumber: Word read FPhysFrameNumber write FPhysFrameNumber;
  359. property PhysOffset: DWord read FPhysOffset write FPhysOffset;
  360. end;
  361. { TOmfSubRecord_FIXUP }
  362. TOmfSubRecord_FIXUP = class
  363. private
  364. FIs32Bit: Boolean;
  365. FMode: TOmfFixupMode;
  366. FLocationType: TOmfFixupLocationType;
  367. FLocationOffset: DWord;
  368. FDataRecordStartOffset: DWord;
  369. FTargetDeterminedByThread: Boolean;
  370. FTargetThread: TOmfFixupThread;
  371. FTargetThreadDisplacementPresent: Boolean;
  372. FTargetMethod: TOmfFixupTargetMethod;
  373. FTargetDatum: Integer;
  374. FTargetDisplacement: DWord;
  375. FFrameDeterminedByThread: Boolean;
  376. FFrameThread: TOmfFixupThread;
  377. FFrameMethod: TOmfFixupFrameMethod;
  378. FFrameDatum: Integer;
  379. function GetDataRecordOffset: Integer;
  380. procedure SetDataRecordOffset(AValue: Integer);
  381. public
  382. function ReadAt(RawRecord: TOmfRawRecord; Offset: Integer): Integer;
  383. function WriteAt(RawRecord: TOmfRawRecord; Offset: Integer): Integer;
  384. property Is32Bit: Boolean read FIs32Bit write FIs32Bit;
  385. property Mode: TOmfFixupMode read FMode write FMode;
  386. property LocationType: TOmfFixupLocationType read FLocationType write FLocationType;
  387. property LocationOffset: DWord read FLocationOffset write FLocationOffset;
  388. property DataRecordStartOffset: DWord read FDataRecordStartOffset write FDataRecordStartOffset;
  389. property DataRecordOffset: Integer read GetDataRecordOffset write SetDataRecordOffset;
  390. property TargetDeterminedByThread: Boolean read FTargetDeterminedByThread write FTargetDeterminedByThread;
  391. property TargetThread: TOmfFixupThread read FTargetThread write FTargetThread;
  392. property TargetThreadDisplacementPresent: Boolean read FTargetThreadDisplacementPresent write FTargetThreadDisplacementPresent;
  393. property TargetMethod: TOmfFixupTargetMethod read FTargetMethod write FTargetMethod;
  394. property TargetDatum: Integer read FTargetDatum write FTargetDatum;
  395. property TargetDisplacement: DWord read FTargetDisplacement write FTargetDisplacement;
  396. property FrameDeterminedByThread: Boolean read FFrameDeterminedByThread write FFrameDeterminedByThread;
  397. property FrameThread: TOmfFixupThread read FFrameThread write FFrameThread;
  398. property FrameMethod: TOmfFixupFrameMethod read FFrameMethod write FFrameMethod;
  399. property FrameDatum: Integer read FFrameDatum write FFrameDatum;
  400. end;
  401. implementation
  402. uses
  403. verbose;
  404. { TOmfOrderedNameCollection }
  405. function TOmfOrderedNameCollection.GetString(Index: Integer): string;
  406. begin
  407. Result:=FStringList[Index-1];
  408. end;
  409. function TOmfOrderedNameCollection.GetCount: Integer;
  410. begin
  411. Result:=Length(FStringList);
  412. end;
  413. procedure TOmfOrderedNameCollection.SetString(Index: Integer; AValue: string);
  414. begin
  415. FStringList[Index-1]:=AValue;
  416. end;
  417. function TOmfOrderedNameCollection.Add(const S: string): Integer;
  418. begin
  419. Result:=Length(FStringList)+1;
  420. SetLength(FStringList,Result);
  421. FStringList[Result-1]:=S;
  422. end;
  423. procedure TOmfOrderedNameCollection.Clear;
  424. begin
  425. SetLength(FStringList,0);
  426. end;
  427. { TOmfRawRecord }
  428. function TOmfRawRecord.GetRecordType: Byte;
  429. begin
  430. Result:=RawData[-3];
  431. end;
  432. procedure TOmfRawRecord.SetRecordType(AValue: Byte);
  433. begin
  434. RawData[-3]:=AValue;
  435. end;
  436. function TOmfRawRecord.GetRecordLength: Word;
  437. begin
  438. Result:=RawData[-2] or (RawData[-1] shl 8);
  439. end;
  440. procedure TOmfRawRecord.SetRecordLength(AValue: Word);
  441. begin
  442. RawData[-2]:=Byte(AValue);
  443. RawData[-1]:=Byte(AValue shr 8);
  444. end;
  445. function TOmfRawRecord.ReadStringAt(Offset: Integer; out s: string): Integer;
  446. var
  447. len: Byte;
  448. begin
  449. len:=RawData[Offset];
  450. Result:=Offset+len+1;
  451. if result>RecordLength then
  452. internalerror(2015033103);
  453. SetLength(s, len);
  454. UniqueString(s);
  455. Move(RawData[Offset+1],s[1],len);
  456. end;
  457. function TOmfRawRecord.WriteStringAt(Offset: Integer; s: string): Integer;
  458. begin
  459. if Length(s)>255 then
  460. internalerror(2015033101);
  461. result:=Offset+Length(s)+1;
  462. if result>High(RawData) then
  463. internalerror(2015033102);
  464. RawData[Offset]:=Length(s);
  465. Move(s[1], RawData[Offset+1], Length(s));
  466. end;
  467. function TOmfRawRecord.ReadIndexedRef(Offset: Integer; out IndexedRef: Integer): Integer;
  468. begin
  469. Result:=Offset+1;
  470. if result>RecordLength then
  471. internalerror(2015033103);
  472. IndexedRef:=RawData[Offset];
  473. if IndexedRef<=$7f then
  474. exit;
  475. Result:=Offset+2;
  476. if result>RecordLength then
  477. internalerror(2015033103);
  478. IndexedRef:=((IndexedRef and $7f) shl 8)+RawData[Offset+1];
  479. end;
  480. function TOmfRawRecord.WriteIndexedRef(Offset: Integer; IndexedRef: Integer): Integer;
  481. begin
  482. if (IndexedRef<0) or (IndexedRef>$7FFF) then
  483. internalerror(2015040303);
  484. if IndexedRef<=$7f then
  485. begin
  486. Result:=Offset+1;
  487. if Result>High(RawData) then
  488. internalerror(2015033102);
  489. RawData[Offset]:=IndexedRef;
  490. end
  491. else
  492. begin
  493. Result:=Offset+2;
  494. if Result>High(RawData) then
  495. internalerror(2015033102);
  496. RawData[Offset]:=$80+(IndexedRef shr 8);
  497. RawData[Offset+1]:=Byte(IndexedRef);
  498. end;
  499. end;
  500. function TOmfRawRecord.GetChecksumByte: Byte;
  501. begin
  502. if RecordLength>0 then
  503. Result:=RawData[RecordLength-1]
  504. else
  505. Result:=0;
  506. end;
  507. procedure TOmfRawRecord.SetChecksumByte(AValue: Byte);
  508. begin
  509. if RecordLength>0 then
  510. RawData[RecordLength-1]:=AValue;
  511. end;
  512. procedure TOmfRawRecord.CalculateChecksumByte;
  513. var
  514. I: Integer;
  515. b: Byte;
  516. begin
  517. b:=0;
  518. for I:=-3 to RecordLength-2 do
  519. b:=byte(b+RawData[I]);
  520. SetChecksumByte($100-b);
  521. end;
  522. function TOmfRawRecord.VerifyChecksumByte: boolean;
  523. var
  524. I: Integer;
  525. b: Byte;
  526. begin
  527. { according to the OMF spec, some tools always write a 0 rather than
  528. computing the checksum, so it should also be accepted as correct }
  529. if ChecksumByte=0 then
  530. exit(true);
  531. b:=0;
  532. for I:=-3 to RecordLength-1 do
  533. b:=byte(b+RawData[I]);
  534. Result:=(b=0);
  535. end;
  536. procedure TOmfRawRecord.ReadFrom(aReader: TObjectReader);
  537. begin
  538. aReader.read(RawData, 3);
  539. aReader.read(RawData[0], RecordLength);
  540. end;
  541. procedure TOmfRawRecord.WriteTo(aWriter: TObjectWriter);
  542. begin
  543. aWriter.write(RawData, RecordLength+3);
  544. end;
  545. { TOmfRecord_THEADR }
  546. procedure TOmfRecord_THEADR.DecodeFrom(RawRecord: TOmfRawRecord);
  547. begin
  548. if RawRecord.RecordType<>RT_THEADR then
  549. internalerror(2015040301);
  550. RawRecord.ReadStringAt(0,FModuleName);
  551. end;
  552. procedure TOmfRecord_THEADR.EncodeTo(RawRecord: TOmfRawRecord);
  553. var
  554. NextOfs: Integer;
  555. begin
  556. RawRecord.RecordType:=RT_THEADR;
  557. NextOfs:=RawRecord.WriteStringAt(0,ModuleName);
  558. RawRecord.RecordLength:=NextOfs+1;
  559. RawRecord.CalculateChecksumByte;
  560. end;
  561. { TOmfRecord_COMENT }
  562. function TOmfRecord_COMENT.GetNoList: Boolean;
  563. begin
  564. Result:=(CommentType and $40)<>0;
  565. end;
  566. function TOmfRecord_COMENT.GetNoPurge: Boolean;
  567. begin
  568. Result:=(CommentType and $80)<>0;
  569. end;
  570. procedure TOmfRecord_COMENT.SetNoList(AValue: Boolean);
  571. begin
  572. if AValue then
  573. CommentType:=CommentType or $40
  574. else
  575. CommentType:=CommentType and $BF;
  576. end;
  577. procedure TOmfRecord_COMENT.SetNoPurge(AValue: Boolean);
  578. begin
  579. if AValue then
  580. CommentType:=CommentType or $80
  581. else
  582. CommentType:=CommentType and $7F;
  583. end;
  584. procedure TOmfRecord_COMENT.DecodeFrom(RawRecord: TOmfRawRecord);
  585. begin
  586. if RawRecord.RecordType<>RT_COMENT then
  587. internalerror(2015040301);
  588. if RawRecord.RecordLength<3 then
  589. internalerror(2015033104);
  590. CommentType:=RawRecord.RawData[0];
  591. CommentClass:=RawRecord.RawData[1];
  592. SetLength(FCommentString,RawRecord.RecordLength-3);
  593. UniqueString(FCommentString);
  594. Move(RawRecord.RawData[2],FCommentString[1],Length(FCommentString));
  595. end;
  596. procedure TOmfRecord_COMENT.EncodeTo(RawRecord: TOmfRawRecord);
  597. begin
  598. RawRecord.RecordType:=RT_COMENT;
  599. if (Length(FCommentString)+3)>High(RawRecord.RawData) then
  600. internalerror(2015033105);
  601. RawRecord.RecordLength:=Length(FCommentString)+3;
  602. RawRecord.RawData[0]:=CommentType;
  603. RawRecord.RawData[1]:=CommentClass;
  604. Move(FCommentString[1],RawRecord.RawData[2],Length(FCommentString));
  605. RawRecord.CalculateChecksumByte;
  606. end;
  607. { TOmfRecord_LNAMES }
  608. constructor TOmfRecord_LNAMES.Create;
  609. begin
  610. FNextIndex:=1;
  611. end;
  612. procedure TOmfRecord_LNAMES.DecodeFrom(RawRecord: TOmfRawRecord);
  613. var
  614. NextOfs: Integer;
  615. Name: string;
  616. begin
  617. if RawRecord.RecordType<>RT_LNAMES then
  618. internalerror(2015040301);
  619. NextOfs:=0;
  620. while NextOfs<(RawRecord.RecordLength-1) do
  621. begin
  622. NextOfs:=RawRecord.ReadStringAt(NextOfs,Name);
  623. Names.Add(Name);
  624. end;
  625. end;
  626. procedure TOmfRecord_LNAMES.EncodeTo(RawRecord: TOmfRawRecord);
  627. const
  628. RecordLengthLimit = 1024;
  629. var
  630. Len,LastIncludedIndex,NextOfs,I: Integer;
  631. begin
  632. RawRecord.RecordType:=RT_LNAMES;
  633. { find out how many strings can we include until we reach the length limit }
  634. Len:=1;
  635. LastIncludedIndex:=NextIndex-1;
  636. repeat
  637. Inc(LastIncludedIndex);
  638. Inc(Len,Length(Names[LastIncludedIndex])+1);
  639. until (LastIncludedIndex>=Names.Count) or ((Len+Length(Names[LastIncludedIndex+1])+1)>=RecordLengthLimit);
  640. { write the strings... }
  641. NextOfs:=0;
  642. for I:=NextIndex to LastIncludedIndex do
  643. NextOfs:=RawRecord.WriteStringAt(NextOfs,Names[I]);
  644. RawRecord.RecordLength:=Len;
  645. RawRecord.CalculateChecksumByte;
  646. { update NextIndex }
  647. NextIndex:=LastIncludedIndex+1;
  648. end;
  649. { TOmfRecord_SEGDEF }
  650. procedure TOmfRecord_SEGDEF.DecodeFrom(RawRecord: TOmfRawRecord);
  651. var
  652. B: Byte;
  653. Big: Boolean;
  654. NextOfs: Integer;
  655. MinLen: Integer;
  656. begin
  657. if not (RawRecord.RecordType in [RT_SEGDEF,RT_SEGDEF32]) then
  658. internalerror(2015040301);
  659. Is32Bit:=RawRecord.RecordType=RT_SEGDEF32;
  660. MinLen:=7; { b(1)+seglength(2..4)+segnameindex(1..2)+classnameindex(1..2)+overlaynameindex(1..2)+checksum }
  661. if Is32Bit then
  662. inc(MinLen,2);
  663. if RawRecord.RecordLength<MinLen then
  664. internalerror(2015040305);
  665. B:=RawRecord.RawData[0];
  666. Alignment:=TOmfSegmentAlignment(B shr 5);
  667. Combination:=TOmfSegmentCombination((B shr 2) and 7);
  668. Big:=(B and 2)<>0;
  669. Use:=TOmfSegmentUse(B and 1);
  670. NextOfs:=1;
  671. if Alignment=saAbsolute then
  672. begin
  673. inc(MinLen,3);
  674. if RawRecord.RecordLength<MinLen then
  675. internalerror(2015040305);
  676. FrameNumber:=RawRecord.RawData[1]+(RawRecord.RawData[2] shl 8);
  677. Offset:=RawRecord.RawData[3];
  678. NextOfs:=4;
  679. end
  680. else
  681. begin
  682. FrameNumber:=0;
  683. Offset:=0;
  684. end;
  685. if Is32Bit then
  686. begin
  687. SegmentLength:=RawRecord.RawData[NextOfs]+
  688. (RawRecord.RawData[NextOfs+1] shl 8)+
  689. (RawRecord.RawData[NextOfs+2] shl 16)+
  690. (RawRecord.RawData[NextOfs+3] shl 24);
  691. if Big then
  692. if SegmentLength=0 then
  693. SegmentLength:=4294967296
  694. else
  695. internalerror(2015040306);
  696. Inc(NextOfs,4);
  697. end
  698. else
  699. begin
  700. SegmentLength:=RawRecord.RawData[NextOfs]+(RawRecord.RawData[NextOfs+1] shl 8);
  701. if Big then
  702. if SegmentLength=0 then
  703. SegmentLength:=65536
  704. else
  705. internalerror(2015040306);
  706. Inc(NextOfs,2);
  707. end;
  708. NextOfs:=RawRecord.ReadIndexedRef(NextOfs,FSegmentNameIndex);
  709. NextOfs:=RawRecord.ReadIndexedRef(NextOfs,FClassNameIndex);
  710. NextOfs:=RawRecord.ReadIndexedRef(NextOfs,FOverlayNameIndex);
  711. end;
  712. procedure TOmfRecord_SEGDEF.EncodeTo(RawRecord: TOmfRawRecord);
  713. var
  714. Big: Boolean;
  715. NextOfs: Integer;
  716. begin
  717. if Is32Bit then
  718. begin
  719. RawRecord.RecordType:=RT_SEGDEF32;
  720. if SegmentLength>4294967296 then
  721. internalerror(2015040302);
  722. Big:=SegmentLength=4294967296;
  723. end
  724. else
  725. begin
  726. RawRecord.RecordType:=RT_SEGDEF;
  727. if SegmentLength>65536 then
  728. internalerror(2015040302);
  729. Big:=SegmentLength=65536;
  730. end;
  731. RawRecord.RawData[0]:=(Ord(Alignment) shl 5) or (Ord(Combination) shl 2) or (Ord(Big) shl 1) or Ord(Use);
  732. NextOfs:=1;
  733. if Alignment=saAbsolute then
  734. begin
  735. RawRecord.RawData[1]:=Byte(FrameNumber);
  736. RawRecord.RawData[2]:=Byte(FrameNumber shr 8);
  737. RawRecord.RawData[3]:=Offset;
  738. NextOfs:=4;
  739. end;
  740. if Is32Bit then
  741. begin
  742. RawRecord.RawData[NextOfs]:=Byte(SegmentLength);
  743. RawRecord.RawData[NextOfs+1]:=Byte(SegmentLength shr 8);
  744. RawRecord.RawData[NextOfs+2]:=Byte(SegmentLength shr 16);
  745. RawRecord.RawData[NextOfs+3]:=Byte(SegmentLength shr 24);
  746. Inc(NextOfs,4);
  747. end
  748. else
  749. begin
  750. RawRecord.RawData[NextOfs]:=Byte(SegmentLength);
  751. RawRecord.RawData[NextOfs+1]:=Byte(SegmentLength shr 8);
  752. Inc(NextOfs,2);
  753. end;
  754. NextOfs:=RawRecord.WriteIndexedRef(NextOfs,SegmentNameIndex);
  755. NextOfs:=RawRecord.WriteIndexedRef(NextOfs,ClassNameIndex);
  756. NextOfs:=RawRecord.WriteIndexedRef(NextOfs,OverlayNameIndex);
  757. RawRecord.RecordLength:=NextOfs+1;
  758. RawRecord.CalculateChecksumByte;
  759. end;
  760. { TOmfRecord_GRPDEF }
  761. procedure TOmfRecord_GRPDEF.DecodeFrom(RawRecord: TOmfRawRecord);
  762. var
  763. NextOfs: Integer;
  764. Segment: Integer;
  765. begin
  766. if RawRecord.RecordType<>RT_GRPDEF then
  767. internalerror(2015040301);
  768. NextOfs:=RawRecord.ReadIndexedRef(0,FGroupNameIndex);
  769. SetLength(FSegmentList,0);
  770. while NextOfs<RawRecord.RecordLength-1 do
  771. begin
  772. if RawRecord.RawData[NextOfs]<>$ff then
  773. internalerror(2015040901);
  774. NextOfs:=RawRecord.ReadIndexedRef(NextOfs+1,Segment);
  775. SetLength(FSegmentList,Length(FSegmentList)+1);
  776. FSegmentList[High(FSegmentList)]:=Segment;
  777. end;
  778. end;
  779. procedure TOmfRecord_GRPDEF.EncodeTo(RawRecord: TOmfRawRecord);
  780. var
  781. NextOfs: Integer;
  782. Segment: Integer;
  783. begin
  784. RawRecord.RecordType:=RT_GRPDEF;
  785. NextOfs:=RawRecord.WriteIndexedRef(0,GroupNameIndex);
  786. for Segment in SegmentList do
  787. begin
  788. if NextOfs>High(RawRecord.RawData) then
  789. internalerror(2015040401);
  790. RawRecord.RawData[NextOfs]:=$ff;
  791. NextOfs:=RawRecord.WriteIndexedRef(NextOfs+1,Segment);
  792. end;
  793. RawRecord.RecordLength:=NextOfs+1;
  794. RawRecord.CalculateChecksumByte;
  795. end;
  796. { TOmfPublicNameElement }
  797. function TOmfPublicNameElement.GetLengthInFile(Is32Bit: Boolean): Integer;
  798. begin
  799. Result:=1+Length(Name)+2+1;
  800. if Is32Bit then
  801. Inc(Result,2);
  802. if TypeIndex>=$80 then
  803. Inc(Result);
  804. end;
  805. { TOmfRecord_PUBDEF }
  806. procedure TOmfRecord_PUBDEF.DecodeFrom(RawRecord: TOmfRawRecord);
  807. var
  808. NextOfs: Integer;
  809. Name: string;
  810. TypeIndex: Integer;
  811. PublicOffset: DWord;
  812. PubName: TOmfPublicNameElement;
  813. begin
  814. if not (RawRecord.RecordType in [RT_PUBDEF,RT_PUBDEF32]) then
  815. internalerror(2015040301);
  816. Is32Bit:=RawRecord.RecordType=RT_PUBDEF32;
  817. NextOfs:=RawRecord.ReadIndexedRef(0,FBaseGroupIndex);
  818. NextOfs:=RawRecord.ReadIndexedRef(NextOfs,FBaseSegmentIndex);
  819. if BaseSegmentIndex=0 then
  820. begin
  821. if (NextOfs+1)>High(RawRecord.RawData) then
  822. internalerror(2015041401);
  823. BaseFrame:=RawRecord.RawData[NextOfs]+(RawRecord.RawData[NextOfs+1] shl 8);
  824. Inc(NextOfs,2);
  825. end
  826. else
  827. BaseFrame:=0;
  828. while NextOfs<(RawRecord.RecordLength-1) do
  829. begin
  830. NextOfs:=RawRecord.ReadStringAt(NextOfs,Name);
  831. if Is32Bit then
  832. begin
  833. if (NextOfs+3)>High(RawRecord.RawData) then
  834. internalerror(2015041401);
  835. PublicOffset:=RawRecord.RawData[NextOfs]+(RawRecord.RawData[NextOfs+1] shl 8)+
  836. (RawRecord.RawData[NextOfs+2] shl 16)+(RawRecord.RawData[NextOfs+3] shl 24);
  837. Inc(NextOfs,4);
  838. end
  839. else
  840. begin
  841. if (NextOfs+1)>High(RawRecord.RawData) then
  842. internalerror(2015041401);
  843. PublicOffset:=RawRecord.RawData[NextOfs]+(RawRecord.RawData[NextOfs+1] shl 8);
  844. Inc(NextOfs,2);
  845. end;
  846. NextOfs:=RawRecord.ReadIndexedRef(NextOfs,TypeIndex);
  847. PubName:=TOmfPublicNameElement.Create(PublicNames,Name);
  848. PubName.PublicOffset:=PublicOffset;
  849. PubName.TypeIndex:=TypeIndex;
  850. end;
  851. end;
  852. procedure TOmfRecord_PUBDEF.EncodeTo(RawRecord: TOmfRawRecord);
  853. const
  854. RecordLengthLimit = 1024;
  855. var
  856. Len,LastIncludedIndex,NextOfs,I: Integer;
  857. PubName: TOmfPublicNameElement;
  858. begin
  859. if Is32Bit then
  860. RawRecord.RecordType:=RT_PUBDEF32
  861. else
  862. RawRecord.RecordType:=RT_PUBDEF;
  863. NextOfs:=RawRecord.WriteIndexedRef(0,BaseGroupIndex);
  864. NextOfs:=RawRecord.WriteIndexedRef(NextOfs,BaseSegmentIndex);
  865. if BaseSegmentIndex=0 then
  866. begin
  867. RawRecord.RawData[NextOfs]:=Byte(BaseFrame);
  868. RawRecord.RawData[NextOfs+1]:=Byte(BaseFrame shr 8);
  869. Inc(NextOfs,2);
  870. end;
  871. { find out how many public names can we include until we reach the length limit }
  872. Len:=NextOfs;
  873. LastIncludedIndex:=NextIndex-1;
  874. repeat
  875. Inc(LastIncludedIndex);
  876. Inc(Len,TOmfPublicNameElement(PublicNames[LastIncludedIndex]).GetLengthInFile(Is32Bit));
  877. until (LastIncludedIndex>=(PublicNames.Count-1)) or ((Len+TOmfPublicNameElement(PublicNames[LastIncludedIndex+1]).GetLengthInFile(Is32Bit))>=RecordLengthLimit);
  878. { write the public names... }
  879. for I:=NextIndex to LastIncludedIndex do
  880. begin
  881. PubName:=TOmfPublicNameElement(PublicNames[I]);
  882. NextOfs:=RawRecord.WriteStringAt(NextOfs,PubName.Name);
  883. if Is32Bit then
  884. begin
  885. RawRecord.RawData[NextOfs]:=Byte(PubName.PublicOffset);
  886. RawRecord.RawData[NextOfs+1]:=Byte(PubName.PublicOffset shr 8);
  887. RawRecord.RawData[NextOfs+2]:=Byte(PubName.PublicOffset shr 16);
  888. RawRecord.RawData[NextOfs+3]:=Byte(PubName.PublicOffset shr 24);
  889. Inc(NextOfs,4);
  890. end
  891. else
  892. begin
  893. if PubName.PublicOffset>$ffff then
  894. internalerror(2015041403);
  895. RawRecord.RawData[NextOfs]:=Byte(PubName.PublicOffset);
  896. RawRecord.RawData[NextOfs+1]:=Byte(PubName.PublicOffset shr 8);
  897. Inc(NextOfs,2);
  898. end;
  899. NextOfs:=RawRecord.WriteIndexedRef(NextOfs,PubName.TypeIndex);
  900. end;
  901. RawRecord.RecordLength:=Len+1;
  902. RawRecord.CalculateChecksumByte;
  903. { update NextIndex }
  904. NextIndex:=LastIncludedIndex+1;
  905. end;
  906. { TOmfExternalNameElement }
  907. function TOmfExternalNameElement.GetLengthInFile: Integer;
  908. begin
  909. Result:=1+Length(Name)+1;
  910. if TypeIndex>=$80 then
  911. Inc(Result);
  912. end;
  913. { TOmfRecord_EXTDEF }
  914. procedure TOmfRecord_EXTDEF.DecodeFrom(RawRecord: TOmfRawRecord);
  915. var
  916. NextOfs: Integer;
  917. Name: string;
  918. TypeIndex: Integer;
  919. ExtName: TOmfExternalNameElement;
  920. begin
  921. if RawRecord.RecordType<>RT_EXTDEF then
  922. internalerror(2015040301);
  923. NextOfs:=0;
  924. while NextOfs<(RawRecord.RecordLength-1) do
  925. begin
  926. NextOfs:=RawRecord.ReadStringAt(NextOfs,Name);
  927. NextOfs:=RawRecord.ReadIndexedRef(NextOfs,TypeIndex);
  928. ExtName:=TOmfExternalNameElement.Create(ExternalNames,Name);
  929. ExtName.TypeIndex:=TypeIndex;
  930. end;
  931. end;
  932. procedure TOmfRecord_EXTDEF.EncodeTo(RawRecord: TOmfRawRecord);
  933. const
  934. RecordLengthLimit = 1024;
  935. var
  936. Len,LastIncludedIndex,NextOfs,I: Integer;
  937. ExtName: TOmfExternalNameElement;
  938. begin
  939. RawRecord.RecordType:=RT_EXTDEF;
  940. NextOfs:=0;
  941. { find out how many external names can we include until we reach the length limit }
  942. Len:=NextOfs;
  943. LastIncludedIndex:=NextIndex-1;
  944. repeat
  945. Inc(LastIncludedIndex);
  946. Inc(Len,TOmfExternalNameElement(ExternalNames[LastIncludedIndex]).GetLengthInFile);
  947. until (LastIncludedIndex>=(ExternalNames.Count-1)) or ((Len+TOmfExternalNameElement(ExternalNames[LastIncludedIndex+1]).GetLengthInFile)>=RecordLengthLimit);
  948. { write the external names... }
  949. for I:=NextIndex to LastIncludedIndex do
  950. begin
  951. ExtName:=TOmfExternalNameElement(ExternalNames[I]);
  952. NextOfs:=RawRecord.WriteStringAt(NextOfs,ExtName.Name);
  953. NextOfs:=RawRecord.WriteIndexedRef(NextOfs,ExtName.TypeIndex);
  954. end;
  955. RawRecord.RecordLength:=Len+1;
  956. RawRecord.CalculateChecksumByte;
  957. { update NextIndex }
  958. NextIndex:=LastIncludedIndex+1;
  959. end;
  960. { TOmfRecord_MODEND }
  961. procedure TOmfRecord_MODEND.DecodeFrom(RawRecord: TOmfRawRecord);
  962. var
  963. ModTyp: Byte;
  964. NextOfs: Integer;
  965. EndData: Byte;
  966. begin
  967. if not (RawRecord.RecordType in [RT_MODEND,RT_MODEND32]) then
  968. internalerror(2015040301);
  969. Is32Bit:=RawRecord.RecordType=RT_MODEND32;
  970. if RawRecord.RecordLength<2 then
  971. internalerror(2015040305);
  972. ModTyp:=RawRecord.RawData[0];
  973. IsMainModule:=(ModTyp and $80)<>0;
  974. HasStartAddress:=(ModTyp and $40)<>0;
  975. SegmentBit:=(ModTyp and $20)<>0;
  976. LogicalStartAddress:=(ModTyp and $01)<>0;
  977. if (ModTyp and $1E)<>0 then
  978. internalerror(2015041404);
  979. NextOfs:=1;
  980. { clear all the start address properties first }
  981. FrameMethod:=Low(FrameMethod);
  982. FrameDatum:=0;
  983. TargetMethod:=Low(TargetMethod);
  984. TargetDatum:=0;
  985. TargetDisplacement:=0;
  986. PhysFrameNumber:=0;
  987. PhysOffset:=0;
  988. if HasStartAddress then
  989. begin
  990. if LogicalStartAddress then
  991. begin
  992. if EndData>=RawRecord.RecordLength then
  993. internalerror(2015040305);
  994. EndData:=RawRecord.RawData[NextOfs];
  995. Inc(NextOfs);
  996. { frame and target method determined by thread is not allowed in MODEND records }
  997. if (EndData and $88)<>0 then
  998. internalerror(2015041406);
  999. FrameMethod:=TOmfFixupFrameMethod((EndData shr 4) and 7);
  1000. TargetMethod:=TOmfFixupTargetMethod(EndData and 7);
  1001. { frame method ffmLocation is not allowed in an MODEND record }
  1002. if FrameMethod=ffmLocation then
  1003. internalerror(2015041402);
  1004. { read Frame Datum? }
  1005. if FrameMethod in [ffmSegmentIndex,ffmGroupIndex,ffmExternalIndex,ffmFrameNumber] then
  1006. NextOfs:=RawRecord.ReadIndexedRef(NextOfs,FFrameDatum);
  1007. { read Target Datum? }
  1008. NextOfs:=RawRecord.ReadIndexedRef(NextOfs,FTargetDatum);
  1009. { read Target Displacement? }
  1010. if TargetMethod in [ftmSegmentIndex,ftmGroupIndex,ftmExternalIndex,ftmFrameNumber] then
  1011. begin
  1012. if Is32Bit then
  1013. begin
  1014. if (NextOfs+3)>=RawRecord.RecordLength then
  1015. internalerror(2015040504);
  1016. TargetDisplacement := RawRecord.RawData[NextOfs]+
  1017. (RawRecord.RawData[NextOfs+1] shl 8)+
  1018. (RawRecord.RawData[NextOfs+2] shl 16)+
  1019. (RawRecord.RawData[NextOfs+3] shl 24);
  1020. Inc(NextOfs,4);
  1021. end
  1022. else
  1023. begin
  1024. if (NextOfs+1)>=RawRecord.RecordLength then
  1025. internalerror(2015040504);
  1026. TargetDisplacement := RawRecord.RawData[NextOfs]+
  1027. (RawRecord.RawData[NextOfs+1] shl 8);
  1028. Inc(NextOfs,2);
  1029. end;
  1030. end;
  1031. end
  1032. else
  1033. begin
  1034. { physical start address }
  1035. if (NextOfs+1)>=RawRecord.RecordLength then
  1036. internalerror(2015040305);
  1037. PhysFrameNumber:=RawRecord.RawData[NextOfs]+(RawRecord.RawData[NextOfs+1] shl 8);
  1038. Inc(NextOfs,2);
  1039. if Is32Bit then
  1040. begin
  1041. if (NextOfs+3)>=RawRecord.RecordLength then
  1042. internalerror(2015040305);
  1043. PhysOffset:=RawRecord.RawData[NextOfs]+(RawRecord.RawData[NextOfs+1] shl 8)+
  1044. (RawRecord.RawData[NextOfs+2] shl 16)+(RawRecord.RawData[NextOfs+3] shl 24);
  1045. Inc(NextOfs,4);
  1046. end
  1047. else
  1048. begin
  1049. if (NextOfs+1)>=RawRecord.RecordLength then
  1050. internalerror(2015040305);
  1051. PhysOffset:=RawRecord.RawData[NextOfs]+(RawRecord.RawData[NextOfs+1] shl 8);
  1052. Inc(NextOfs,2);
  1053. end;
  1054. end;
  1055. end;
  1056. end;
  1057. procedure TOmfRecord_MODEND.EncodeTo(RawRecord: TOmfRawRecord);
  1058. var
  1059. ModTyp: Byte;
  1060. NextOfs: Integer;
  1061. EndData: Byte;
  1062. begin
  1063. if Is32Bit then
  1064. RawRecord.RecordType:=RT_MODEND32
  1065. else
  1066. RawRecord.RecordType:=RT_MODEND;
  1067. ModTyp:=(Ord(IsMainModule) shl 7)+(Ord(HasStartAddress) shl 6)+(Ord(SegmentBit) shl 5)+Ord(LogicalStartAddress);
  1068. RawRecord.RawData[0]:=ModTyp;
  1069. NextOfs:=1;
  1070. if HasStartAddress then
  1071. begin
  1072. if LogicalStartAddress then
  1073. begin
  1074. { frame method ffmLocation is not allowed in an MODEND record }
  1075. if FrameMethod=ffmLocation then
  1076. internalerror(2015041402);
  1077. EndData:=(Ord(FrameMethod) shl 4)+Ord(TargetMethod);
  1078. RawRecord.RawData[NextOfs]:=EndData;
  1079. Inc(NextOfs);
  1080. { save Frame Datum? }
  1081. if FrameMethod in [ffmSegmentIndex,ffmGroupIndex,ffmExternalIndex,ffmFrameNumber] then
  1082. NextOfs:=RawRecord.WriteIndexedRef(NextOfs,FrameDatum);
  1083. { save Target Datum? }
  1084. NextOfs:=RawRecord.WriteIndexedRef(NextOfs,TargetDatum);
  1085. { save Target Displacement? }
  1086. if TargetMethod in [ftmSegmentIndex,ftmGroupIndex,ftmExternalIndex,ftmFrameNumber] then
  1087. begin
  1088. if Is32Bit then
  1089. begin
  1090. RawRecord.RawData[NextOfs]:=Byte(TargetDisplacement);
  1091. RawRecord.RawData[NextOfs+1]:=Byte(TargetDisplacement shr 8);
  1092. RawRecord.RawData[NextOfs+2]:=Byte(TargetDisplacement shr 16);
  1093. RawRecord.RawData[NextOfs+3]:=Byte(TargetDisplacement shr 24);
  1094. Inc(NextOfs,4);
  1095. end
  1096. else
  1097. begin
  1098. if TargetDisplacement>$ffff then
  1099. internalerror(2015040502);
  1100. RawRecord.RawData[NextOfs]:=Byte(TargetDisplacement);
  1101. RawRecord.RawData[NextOfs+1]:=Byte(TargetDisplacement shr 8);
  1102. Inc(NextOfs,2);
  1103. end;
  1104. end;
  1105. end
  1106. else
  1107. begin
  1108. { physical start address }
  1109. RawRecord.RawData[NextOfs]:=Byte(PhysFrameNumber);
  1110. RawRecord.RawData[NextOfs+1]:=Byte(PhysFrameNumber shr 8);
  1111. Inc(NextOfs,2);
  1112. if Is32Bit then
  1113. begin
  1114. RawRecord.RawData[NextOfs]:=Byte(PhysOffset);
  1115. RawRecord.RawData[NextOfs+1]:=Byte(PhysOffset shr 8);
  1116. RawRecord.RawData[NextOfs+2]:=Byte(PhysOffset shr 16);
  1117. RawRecord.RawData[NextOfs+3]:=Byte(PhysOffset shr 24);
  1118. Inc(NextOfs,4);
  1119. end
  1120. else
  1121. begin
  1122. if PhysOffset>$ffff then
  1123. internalerror(2015040502);
  1124. RawRecord.RawData[NextOfs]:=Byte(PhysOffset);
  1125. RawRecord.RawData[NextOfs+1]:=Byte(PhysOffset shr 8);
  1126. Inc(NextOfs,2);
  1127. end;
  1128. end;
  1129. end;
  1130. RawRecord.RecordLength:=NextOfs+1;
  1131. RawRecord.CalculateChecksumByte;
  1132. end;
  1133. { TOmfSubRecord_FIXUP }
  1134. function TOmfSubRecord_FIXUP.GetDataRecordOffset: Integer;
  1135. begin
  1136. Result:=FLocationOffset-FDataRecordStartOffset;
  1137. end;
  1138. procedure TOmfSubRecord_FIXUP.SetDataRecordOffset(AValue: Integer);
  1139. begin
  1140. FLocationOffset:=AValue+FDataRecordStartOffset;
  1141. end;
  1142. function TOmfSubRecord_FIXUP.ReadAt(RawRecord: TOmfRawRecord; Offset: Integer): Integer;
  1143. var
  1144. Locat: Word;
  1145. FixData: Byte;
  1146. begin
  1147. if (Offset+2)>High(RawRecord.RawData) then
  1148. internalerror(2015040504);
  1149. { unlike other fields in the OMF format, this one is big endian }
  1150. Locat:=(RawRecord.RawData[Offset] shl 8) or RawRecord.RawData[Offset+1];
  1151. FixData:=RawRecord.RawData[Offset+2];
  1152. Inc(Offset,3);
  1153. if (Locat and $8000)=0 then
  1154. internalerror(2015040503);
  1155. DataRecordOffset:=Locat and $3FF;
  1156. LocationType:=TOmfFixupLocationType((Locat shr 10) and 15);
  1157. Mode:=TOmfFixupMode((Locat shr 14) and 1);
  1158. FrameDeterminedByThread:=(FixData and $80)<>0;
  1159. TargetDeterminedByThread:=(FixData and $08)<>0;
  1160. if FrameDeterminedByThread then
  1161. FrameThread:=TOmfFixupThread((FixData shr 4) and 3)
  1162. else
  1163. FrameMethod:=TOmfFixupFrameMethod((FixData shr 4) and 7);
  1164. if TargetDeterminedByThread then
  1165. begin
  1166. TargetThread:=TOmfFixupThread(FixData and 3);
  1167. TargetThreadDisplacementPresent:=(FixData and $40)=0;
  1168. end
  1169. else
  1170. TargetMethod:=TOmfFixupTargetMethod(FixData and 7);
  1171. { read Frame Datum? }
  1172. if not FrameDeterminedByThread and (FrameMethod in [ffmSegmentIndex,ffmGroupIndex,ffmExternalIndex,ffmFrameNumber]) then
  1173. Offset:=RawRecord.ReadIndexedRef(Offset,FFrameDatum)
  1174. else
  1175. FrameDatum:=0;
  1176. { read Target Datum? }
  1177. if not TargetDeterminedByThread then
  1178. Offset:=RawRecord.ReadIndexedRef(Offset,FTargetDatum)
  1179. else
  1180. TargetDatum:=0;
  1181. { read Target Displacement? }
  1182. if (TargetDeterminedByThread and TargetThreadDisplacementPresent) or
  1183. (TargetMethod in [ftmSegmentIndex,ftmGroupIndex,ftmExternalIndex,ftmFrameNumber]) then
  1184. begin
  1185. if Is32Bit then
  1186. begin
  1187. if (Offset+3)>High(RawRecord.RawData) then
  1188. internalerror(2015040504);
  1189. TargetDisplacement := RawRecord.RawData[Offset]+
  1190. (RawRecord.RawData[Offset+1] shl 8)+
  1191. (RawRecord.RawData[Offset+2] shl 16)+
  1192. (RawRecord.RawData[Offset+3] shl 24);
  1193. Inc(Offset,4);
  1194. end
  1195. else
  1196. begin
  1197. if (Offset+1)>High(RawRecord.RawData) then
  1198. internalerror(2015040504);
  1199. TargetDisplacement := RawRecord.RawData[Offset]+
  1200. (RawRecord.RawData[Offset+1] shl 8);
  1201. Inc(Offset,2);
  1202. end;
  1203. end;
  1204. Result:=Offset;
  1205. end;
  1206. function TOmfSubRecord_FIXUP.WriteAt(RawRecord: TOmfRawRecord; Offset: Integer): Integer;
  1207. var
  1208. Locat: Word;
  1209. FixData: Byte;
  1210. begin
  1211. if (DataRecordOffset<0) or (DataRecordOffset>1023) then
  1212. internalerror(2015040501);
  1213. Locat:=$8000+(Ord(Mode) shl 14)+(Ord(LocationType) shl 10)+DataRecordOffset;
  1214. { unlike other fields in the OMF format, this one is big endian }
  1215. RawRecord.RawData[Offset]:=Byte(Locat shr 8);
  1216. RawRecord.RawData[Offset+1]:=Byte(Locat);
  1217. Inc(Offset, 2);
  1218. FixData:=(Ord(FrameDeterminedByThread) shl 7)+(Ord(TargetDeterminedByThread) shl 3);
  1219. if FrameDeterminedByThread then
  1220. FixData:=FixData+(Ord(FrameThread) shl 4)
  1221. else
  1222. FixData:=FixData+(Ord(FrameMethod) shl 4);
  1223. if TargetDeterminedByThread then
  1224. FixData:=FixData+Ord(TargetThread)+(Ord(not TargetThreadDisplacementPresent) shl 2)
  1225. else
  1226. FixData:=FixData+Ord(TargetMethod);
  1227. RawRecord.RawData[Offset]:=FixData;
  1228. Inc(Offset);
  1229. { save Frame Datum? }
  1230. if not FrameDeterminedByThread and (FrameMethod in [ffmSegmentIndex,ffmGroupIndex,ffmExternalIndex,ffmFrameNumber]) then
  1231. Offset:=RawRecord.WriteIndexedRef(Offset,FrameDatum);
  1232. { save Target Datum? }
  1233. if not TargetDeterminedByThread then
  1234. Offset:=RawRecord.WriteIndexedRef(Offset,TargetDatum);
  1235. { save Target Displacement? }
  1236. if (TargetDeterminedByThread and TargetThreadDisplacementPresent) or
  1237. (TargetMethod in [ftmSegmentIndex,ftmGroupIndex,ftmExternalIndex,ftmFrameNumber]) then
  1238. begin
  1239. if Is32Bit then
  1240. begin
  1241. RawRecord.RawData[Offset]:=Byte(TargetDisplacement);
  1242. RawRecord.RawData[Offset+1]:=Byte(TargetDisplacement shr 8);
  1243. RawRecord.RawData[Offset+2]:=Byte(TargetDisplacement shr 16);
  1244. RawRecord.RawData[Offset+3]:=Byte(TargetDisplacement shr 24);
  1245. Inc(Offset,4);
  1246. end
  1247. else
  1248. begin
  1249. if TargetDisplacement>$ffff then
  1250. internalerror(2015040502);
  1251. RawRecord.RawData[Offset]:=Byte(TargetDisplacement);
  1252. RawRecord.RawData[Offset+1]:=Byte(TargetDisplacement shr 8);
  1253. Inc(Offset,2);
  1254. end;
  1255. end;
  1256. Result:=Offset;
  1257. end;
  1258. end.