omfbase.pas 40 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159
  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. public
  337. procedure DecodeFrom(RawRecord: TOmfRawRecord);override;
  338. procedure EncodeTo(RawRecord: TOmfRawRecord);override;
  339. property Is32Bit: Boolean read FIs32Bit write FIs32Bit;
  340. property IsMainModule: Boolean read FIsMainModule write FIsMainModule;
  341. property HasStartAddress: Boolean read FHasStartAddress write FHasStartAddress;
  342. property SegmentBit: Boolean read FSegmentBit write FSegmentBit;
  343. property LogicalStartAddress: Boolean read FLogicalStartAddress write FLogicalStartAddress;
  344. end;
  345. { TOmfSubRecord_FIXUP }
  346. TOmfSubRecord_FIXUP = class
  347. private
  348. FIs32Bit: Boolean;
  349. FMode: TOmfFixupMode;
  350. FLocationType: TOmfFixupLocationType;
  351. FLocationOffset: DWord;
  352. FDataRecordStartOffset: DWord;
  353. FTargetDeterminedByThread: Boolean;
  354. FTargetThread: TOmfFixupThread;
  355. FTargetThreadDisplacementPresent: Boolean;
  356. FTargetMethod: TOmfFixupTargetMethod;
  357. FTargetDatum: Integer;
  358. FTargetDisplacement: DWord;
  359. FFrameDeterminedByThread: Boolean;
  360. FFrameThread: TOmfFixupThread;
  361. FFrameMethod: TOmfFixupFrameMethod;
  362. FFrameDatum: Integer;
  363. function GetDataRecordOffset: Integer;
  364. procedure SetDataRecordOffset(AValue: Integer);
  365. public
  366. function ReadAt(RawRecord: TOmfRawRecord; Offset: Integer): Integer;
  367. function WriteAt(RawRecord: TOmfRawRecord; Offset: Integer): Integer;
  368. property Is32Bit: Boolean read FIs32Bit write FIs32Bit;
  369. property Mode: TOmfFixupMode read FMode write FMode;
  370. property LocationType: TOmfFixupLocationType read FLocationType write FLocationType;
  371. property LocationOffset: DWord read FLocationOffset write FLocationOffset;
  372. property DataRecordStartOffset: DWord read FDataRecordStartOffset write FDataRecordStartOffset;
  373. property DataRecordOffset: Integer read GetDataRecordOffset write SetDataRecordOffset;
  374. property TargetDeterminedByThread: Boolean read FTargetDeterminedByThread write FTargetDeterminedByThread;
  375. property TargetThread: TOmfFixupThread read FTargetThread write FTargetThread;
  376. property TargetThreadDisplacementPresent: Boolean read FTargetThreadDisplacementPresent write FTargetThreadDisplacementPresent;
  377. property TargetMethod: TOmfFixupTargetMethod read FTargetMethod write FTargetMethod;
  378. property TargetDatum: Integer read FTargetDatum write FTargetDatum;
  379. property TargetDisplacement: DWord read FTargetDisplacement write FTargetDisplacement;
  380. property FrameDeterminedByThread: Boolean read FFrameDeterminedByThread write FFrameDeterminedByThread;
  381. property FrameThread: TOmfFixupThread read FFrameThread write FFrameThread;
  382. property FrameMethod: TOmfFixupFrameMethod read FFrameMethod write FFrameMethod;
  383. property FrameDatum: Integer read FFrameDatum write FFrameDatum;
  384. end;
  385. implementation
  386. uses
  387. verbose;
  388. { TOmfOrderedNameCollection }
  389. function TOmfOrderedNameCollection.GetString(Index: Integer): string;
  390. begin
  391. Result:=FStringList[Index-1];
  392. end;
  393. function TOmfOrderedNameCollection.GetCount: Integer;
  394. begin
  395. Result:=Length(FStringList);
  396. end;
  397. procedure TOmfOrderedNameCollection.SetString(Index: Integer; AValue: string);
  398. begin
  399. FStringList[Index-1]:=AValue;
  400. end;
  401. function TOmfOrderedNameCollection.Add(const S: string): Integer;
  402. begin
  403. Result:=Length(FStringList)+1;
  404. SetLength(FStringList,Result);
  405. FStringList[Result-1]:=S;
  406. end;
  407. procedure TOmfOrderedNameCollection.Clear;
  408. begin
  409. SetLength(FStringList,0);
  410. end;
  411. { TOmfRawRecord }
  412. function TOmfRawRecord.GetRecordType: Byte;
  413. begin
  414. Result:=RawData[-3];
  415. end;
  416. procedure TOmfRawRecord.SetRecordType(AValue: Byte);
  417. begin
  418. RawData[-3]:=AValue;
  419. end;
  420. function TOmfRawRecord.GetRecordLength: Word;
  421. begin
  422. Result:=RawData[-2] or (RawData[-1] shl 8);
  423. end;
  424. procedure TOmfRawRecord.SetRecordLength(AValue: Word);
  425. begin
  426. RawData[-2]:=Byte(AValue);
  427. RawData[-1]:=Byte(AValue shr 8);
  428. end;
  429. function TOmfRawRecord.ReadStringAt(Offset: Integer; out s: string): Integer;
  430. var
  431. len: Byte;
  432. begin
  433. len:=RawData[Offset];
  434. Result:=Offset+len+1;
  435. if result>RecordLength then
  436. internalerror(2015033103);
  437. SetLength(s, len);
  438. UniqueString(s);
  439. Move(RawData[Offset+1],s[1],len);
  440. end;
  441. function TOmfRawRecord.WriteStringAt(Offset: Integer; s: string): Integer;
  442. begin
  443. if Length(s)>255 then
  444. internalerror(2015033101);
  445. result:=Offset+Length(s)+1;
  446. if result>High(RawData) then
  447. internalerror(2015033102);
  448. RawData[Offset]:=Length(s);
  449. Move(s[1], RawData[Offset+1], Length(s));
  450. end;
  451. function TOmfRawRecord.ReadIndexedRef(Offset: Integer; out IndexedRef: Integer): Integer;
  452. begin
  453. Result:=Offset+1;
  454. if result>RecordLength then
  455. internalerror(2015033103);
  456. IndexedRef:=RawData[Offset];
  457. if IndexedRef<=$7f then
  458. exit;
  459. Result:=Offset+2;
  460. if result>RecordLength then
  461. internalerror(2015033103);
  462. IndexedRef:=((IndexedRef and $7f) shl 8)+RawData[Offset+1];
  463. end;
  464. function TOmfRawRecord.WriteIndexedRef(Offset: Integer; IndexedRef: Integer): Integer;
  465. begin
  466. if (IndexedRef<0) or (IndexedRef>$7FFF) then
  467. internalerror(2015040303);
  468. if IndexedRef<=$7f then
  469. begin
  470. Result:=Offset+1;
  471. if Result>High(RawData) then
  472. internalerror(2015033102);
  473. RawData[Offset]:=IndexedRef;
  474. end
  475. else
  476. begin
  477. Result:=Offset+2;
  478. if Result>High(RawData) then
  479. internalerror(2015033102);
  480. RawData[Offset]:=$80+(IndexedRef shr 8);
  481. RawData[Offset+1]:=Byte(IndexedRef);
  482. end;
  483. end;
  484. function TOmfRawRecord.GetChecksumByte: Byte;
  485. begin
  486. if RecordLength>0 then
  487. Result:=RawData[RecordLength-1]
  488. else
  489. Result:=0;
  490. end;
  491. procedure TOmfRawRecord.SetChecksumByte(AValue: Byte);
  492. begin
  493. if RecordLength>0 then
  494. RawData[RecordLength-1]:=AValue;
  495. end;
  496. procedure TOmfRawRecord.CalculateChecksumByte;
  497. var
  498. I: Integer;
  499. b: Byte;
  500. begin
  501. b:=0;
  502. for I:=-3 to RecordLength-2 do
  503. b:=byte(b+RawData[I]);
  504. SetChecksumByte($100-b);
  505. end;
  506. function TOmfRawRecord.VerifyChecksumByte: boolean;
  507. var
  508. I: Integer;
  509. b: Byte;
  510. begin
  511. { according to the OMF spec, some tools always write a 0 rather than
  512. computing the checksum, so it should also be accepted as correct }
  513. if ChecksumByte=0 then
  514. exit(true);
  515. b:=0;
  516. for I:=-3 to RecordLength-1 do
  517. b:=byte(b+RawData[I]);
  518. Result:=(b=0);
  519. end;
  520. procedure TOmfRawRecord.ReadFrom(aReader: TObjectReader);
  521. begin
  522. aReader.read(RawData, 3);
  523. aReader.read(RawData[0], RecordLength);
  524. end;
  525. procedure TOmfRawRecord.WriteTo(aWriter: TObjectWriter);
  526. begin
  527. aWriter.write(RawData, RecordLength+3);
  528. end;
  529. { TOmfRecord_THEADR }
  530. procedure TOmfRecord_THEADR.DecodeFrom(RawRecord: TOmfRawRecord);
  531. begin
  532. RawRecord.ReadStringAt(0,FModuleName);
  533. end;
  534. procedure TOmfRecord_THEADR.EncodeTo(RawRecord: TOmfRawRecord);
  535. var
  536. NextOfs: Integer;
  537. begin
  538. RawRecord.RecordType:=RT_THEADR;
  539. NextOfs:=RawRecord.WriteStringAt(0,ModuleName);
  540. RawRecord.RecordLength:=NextOfs+1;
  541. RawRecord.CalculateChecksumByte;
  542. end;
  543. { TOmfRecord_COMENT }
  544. function TOmfRecord_COMENT.GetNoList: Boolean;
  545. begin
  546. Result:=(CommentType and $40)<>0;
  547. end;
  548. function TOmfRecord_COMENT.GetNoPurge: Boolean;
  549. begin
  550. Result:=(CommentType and $80)<>0;
  551. end;
  552. procedure TOmfRecord_COMENT.SetNoList(AValue: Boolean);
  553. begin
  554. if AValue then
  555. CommentType:=CommentType or $40
  556. else
  557. CommentType:=CommentType and $BF;
  558. end;
  559. procedure TOmfRecord_COMENT.SetNoPurge(AValue: Boolean);
  560. begin
  561. if AValue then
  562. CommentType:=CommentType or $80
  563. else
  564. CommentType:=CommentType and $7F;
  565. end;
  566. procedure TOmfRecord_COMENT.DecodeFrom(RawRecord: TOmfRawRecord);
  567. begin
  568. if RawRecord.RecordLength<3 then
  569. internalerror(2015033104);
  570. CommentType:=RawRecord.RawData[0];
  571. CommentClass:=RawRecord.RawData[1];
  572. SetLength(FCommentString,RawRecord.RecordLength-3);
  573. UniqueString(FCommentString);
  574. Move(RawRecord.RawData[2],FCommentString[1],Length(FCommentString));
  575. end;
  576. procedure TOmfRecord_COMENT.EncodeTo(RawRecord: TOmfRawRecord);
  577. begin
  578. RawRecord.RecordType:=RT_COMENT;
  579. if (Length(FCommentString)+3)>High(RawRecord.RawData) then
  580. internalerror(2015033105);
  581. RawRecord.RecordLength:=Length(FCommentString)+3;
  582. RawRecord.RawData[0]:=CommentType;
  583. RawRecord.RawData[1]:=CommentClass;
  584. Move(FCommentString[1],RawRecord.RawData[2],Length(FCommentString));
  585. RawRecord.CalculateChecksumByte;
  586. end;
  587. { TOmfRecord_LNAMES }
  588. constructor TOmfRecord_LNAMES.Create;
  589. begin
  590. FNextIndex:=1;
  591. end;
  592. procedure TOmfRecord_LNAMES.DecodeFrom(RawRecord: TOmfRawRecord);
  593. begin
  594. {TODO: implement}
  595. internalerror(2015040101);
  596. end;
  597. procedure TOmfRecord_LNAMES.EncodeTo(RawRecord: TOmfRawRecord);
  598. const
  599. RecordLengthLimit = 1024;
  600. var
  601. Len,LastIncludedIndex,NextOfs,I: Integer;
  602. begin
  603. RawRecord.RecordType:=RT_LNAMES;
  604. { find out how many strings can we include until we reach the length limit }
  605. Len:=1;
  606. LastIncludedIndex:=NextIndex-1;
  607. repeat
  608. Inc(LastIncludedIndex);
  609. Inc(Len,Length(Names[LastIncludedIndex])+1);
  610. until (LastIncludedIndex>=Names.Count) or ((Len+Length(Names[LastIncludedIndex+1])+1)>=RecordLengthLimit);
  611. { write the strings... }
  612. NextOfs:=0;
  613. for I:=NextIndex to LastIncludedIndex do
  614. NextOfs:=RawRecord.WriteStringAt(NextOfs,Names[I]);
  615. RawRecord.RecordLength:=Len;
  616. RawRecord.CalculateChecksumByte;
  617. { update NextIndex }
  618. NextIndex:=LastIncludedIndex+1;
  619. end;
  620. { TOmfRecord_SEGDEF }
  621. procedure TOmfRecord_SEGDEF.DecodeFrom(RawRecord: TOmfRawRecord);
  622. var
  623. B: Byte;
  624. Big: Boolean;
  625. NextOfs: Integer;
  626. MinLen: Integer;
  627. begin
  628. if not (RawRecord.RecordType in [RT_SEGDEF,RT_SEGDEF32]) then
  629. internalerror(2015040301);
  630. Is32Bit:=RawRecord.RecordType=RT_SEGDEF32;
  631. MinLen:=7; { b(1)+seglength(2..4)+segnameindex(1..2)+classnameindex(1..2)+overlaynameindex(1..2)+checksum }
  632. if Is32Bit then
  633. inc(MinLen,2);
  634. if RawRecord.RecordLength<MinLen then
  635. internalerror(2015040305);
  636. B:=RawRecord.RawData[0];
  637. Alignment:=TOmfSegmentAlignment(B shr 5);
  638. Combination:=TOmfSegmentCombination((B shr 2) and 7);
  639. Big:=(B and 2)<>0;
  640. Use:=TOmfSegmentUse(B and 1);
  641. NextOfs:=1;
  642. if Alignment=saAbsolute then
  643. begin
  644. inc(MinLen,3);
  645. if RawRecord.RecordLength<MinLen then
  646. internalerror(2015040305);
  647. FrameNumber:=RawRecord.RawData[1]+(RawRecord.RawData[2] shl 8);
  648. Offset:=RawRecord.RawData[3];
  649. NextOfs:=4;
  650. end
  651. else
  652. begin
  653. FrameNumber:=0;
  654. Offset:=0;
  655. end;
  656. if Is32Bit then
  657. begin
  658. SegmentLength:=RawRecord.RawData[NextOfs]+
  659. (RawRecord.RawData[NextOfs+1] shl 8)+
  660. (RawRecord.RawData[NextOfs+2] shl 16)+
  661. (RawRecord.RawData[NextOfs+3] shl 24);
  662. if Big then
  663. if SegmentLength=0 then
  664. SegmentLength:=4294967296
  665. else
  666. internalerror(2015040306);
  667. Inc(NextOfs,4);
  668. end
  669. else
  670. begin
  671. SegmentLength:=RawRecord.RawData[NextOfs]+(RawRecord.RawData[NextOfs+1] shl 8);
  672. if Big then
  673. if SegmentLength=0 then
  674. SegmentLength:=65536
  675. else
  676. internalerror(2015040306);
  677. Inc(NextOfs,2);
  678. end;
  679. NextOfs:=RawRecord.ReadIndexedRef(NextOfs,FSegmentNameIndex);
  680. NextOfs:=RawRecord.ReadIndexedRef(NextOfs,FClassNameIndex);
  681. NextOfs:=RawRecord.ReadIndexedRef(NextOfs,FOverlayNameIndex);
  682. end;
  683. procedure TOmfRecord_SEGDEF.EncodeTo(RawRecord: TOmfRawRecord);
  684. var
  685. Big: Boolean;
  686. NextOfs: Integer;
  687. begin
  688. if Is32Bit then
  689. begin
  690. RawRecord.RecordType:=RT_SEGDEF32;
  691. if SegmentLength>4294967296 then
  692. internalerror(2015040302);
  693. Big:=SegmentLength=4294967296;
  694. end
  695. else
  696. begin
  697. RawRecord.RecordType:=RT_SEGDEF;
  698. if SegmentLength>65536 then
  699. internalerror(2015040302);
  700. Big:=SegmentLength=65536;
  701. end;
  702. RawRecord.RawData[0]:=(Ord(Alignment) shl 5) or (Ord(Combination) shl 2) or (Ord(Big) shl 1) or Ord(Use);
  703. NextOfs:=1;
  704. if Alignment=saAbsolute then
  705. begin
  706. RawRecord.RawData[1]:=Byte(FrameNumber);
  707. RawRecord.RawData[2]:=Byte(FrameNumber shr 8);
  708. RawRecord.RawData[3]:=Offset;
  709. NextOfs:=4;
  710. end;
  711. if Is32Bit then
  712. begin
  713. RawRecord.RawData[NextOfs]:=Byte(SegmentLength);
  714. RawRecord.RawData[NextOfs+1]:=Byte(SegmentLength shr 8);
  715. RawRecord.RawData[NextOfs+2]:=Byte(SegmentLength shr 16);
  716. RawRecord.RawData[NextOfs+3]:=Byte(SegmentLength shr 24);
  717. Inc(NextOfs,4);
  718. end
  719. else
  720. begin
  721. RawRecord.RawData[NextOfs]:=Byte(SegmentLength);
  722. RawRecord.RawData[NextOfs+1]:=Byte(SegmentLength shr 8);
  723. Inc(NextOfs,2);
  724. end;
  725. NextOfs:=RawRecord.WriteIndexedRef(NextOfs,SegmentNameIndex);
  726. NextOfs:=RawRecord.WriteIndexedRef(NextOfs,ClassNameIndex);
  727. NextOfs:=RawRecord.WriteIndexedRef(NextOfs,OverlayNameIndex);
  728. RawRecord.RecordLength:=NextOfs+1;
  729. RawRecord.CalculateChecksumByte;
  730. end;
  731. { TOmfRecord_GRPDEF }
  732. procedure TOmfRecord_GRPDEF.DecodeFrom(RawRecord: TOmfRawRecord);
  733. var
  734. NextOfs: Integer;
  735. Segment: Integer;
  736. begin
  737. if RawRecord.RecordType<>RT_GRPDEF then
  738. internalerror(2015040301);
  739. NextOfs:=RawRecord.ReadIndexedRef(0,FGroupNameIndex);
  740. SetLength(FSegmentList,0);
  741. while NextOfs<RawRecord.RecordLength-1 do
  742. begin
  743. if RawRecord.RawData[NextOfs]<>$ff then
  744. internalerror(2015040901);
  745. NextOfs:=RawRecord.ReadIndexedRef(NextOfs+1,Segment);
  746. SetLength(FSegmentList,Length(FSegmentList)+1);
  747. FSegmentList[High(FSegmentList)]:=Segment;
  748. end;
  749. end;
  750. procedure TOmfRecord_GRPDEF.EncodeTo(RawRecord: TOmfRawRecord);
  751. var
  752. NextOfs: Integer;
  753. Segment: Integer;
  754. begin
  755. RawRecord.RecordType:=RT_GRPDEF;
  756. NextOfs:=RawRecord.WriteIndexedRef(0,GroupNameIndex);
  757. for Segment in SegmentList do
  758. begin
  759. if NextOfs>High(RawRecord.RawData) then
  760. internalerror(2015040401);
  761. RawRecord.RawData[NextOfs]:=$ff;
  762. NextOfs:=RawRecord.WriteIndexedRef(NextOfs+1,Segment);
  763. end;
  764. RawRecord.RecordLength:=NextOfs+1;
  765. RawRecord.CalculateChecksumByte;
  766. end;
  767. { TOmfPublicNameElement }
  768. function TOmfPublicNameElement.GetLengthInFile(Is32Bit: Boolean): Integer;
  769. begin
  770. Result:=1+Length(Name)+2+1;
  771. if Is32Bit then
  772. Inc(Result,2);
  773. if TypeIndex>=$80 then
  774. Inc(Result);
  775. end;
  776. { TOmfRecord_PUBDEF }
  777. procedure TOmfRecord_PUBDEF.DecodeFrom(RawRecord: TOmfRawRecord);
  778. begin
  779. {TODO: implement}
  780. internalerror(2015040101);
  781. end;
  782. procedure TOmfRecord_PUBDEF.EncodeTo(RawRecord: TOmfRawRecord);
  783. const
  784. RecordLengthLimit = 1024;
  785. var
  786. Len,LastIncludedIndex,NextOfs,I: Integer;
  787. PubName: TOmfPublicNameElement;
  788. begin
  789. if Is32Bit then
  790. RawRecord.RecordType:=RT_PUBDEF32
  791. else
  792. RawRecord.RecordType:=RT_PUBDEF;
  793. NextOfs:=RawRecord.WriteIndexedRef(0,BaseGroupIndex);
  794. NextOfs:=RawRecord.WriteIndexedRef(NextOfs,BaseSegmentIndex);
  795. if BaseSegmentIndex=0 then
  796. begin
  797. RawRecord.RawData[NextOfs]:=Byte(BaseFrame);
  798. RawRecord.RawData[NextOfs+1]:=Byte(BaseFrame shr 8);
  799. Inc(NextOfs,2);
  800. end;
  801. { find out how many public names can we include until we reach the length limit }
  802. Len:=NextOfs;
  803. LastIncludedIndex:=NextIndex-1;
  804. repeat
  805. Inc(LastIncludedIndex);
  806. Inc(Len,TOmfPublicNameElement(PublicNames[LastIncludedIndex]).GetLengthInFile(Is32Bit));
  807. until (LastIncludedIndex>=(PublicNames.Count-1)) or ((Len+TOmfPublicNameElement(PublicNames[LastIncludedIndex+1]).GetLengthInFile(Is32Bit))>=RecordLengthLimit);
  808. { write the public names... }
  809. for I:=NextIndex to LastIncludedIndex do
  810. begin
  811. PubName:=TOmfPublicNameElement(PublicNames[I]);
  812. NextOfs:=RawRecord.WriteStringAt(NextOfs,PubName.Name);
  813. if Is32Bit then
  814. begin
  815. RawRecord.RawData[NextOfs]:=Byte(PubName.PublicOffset);
  816. RawRecord.RawData[NextOfs+1]:=Byte(PubName.PublicOffset shr 8);
  817. RawRecord.RawData[NextOfs+2]:=Byte(PubName.PublicOffset shr 16);
  818. RawRecord.RawData[NextOfs+3]:=Byte(PubName.PublicOffset shr 24);
  819. Inc(NextOfs,4);
  820. end
  821. else
  822. begin
  823. RawRecord.RawData[NextOfs]:=Byte(PubName.PublicOffset);
  824. RawRecord.RawData[NextOfs+1]:=Byte(PubName.PublicOffset shr 8);
  825. Inc(NextOfs,2);
  826. end;
  827. NextOfs:=RawRecord.WriteIndexedRef(NextOfs,PubName.TypeIndex);
  828. end;
  829. RawRecord.RecordLength:=Len+1;
  830. RawRecord.CalculateChecksumByte;
  831. { update NextIndex }
  832. NextIndex:=LastIncludedIndex+1;
  833. end;
  834. { TOmfExternalNameElement }
  835. function TOmfExternalNameElement.GetLengthInFile: Integer;
  836. begin
  837. Result:=1+Length(Name)+1;
  838. if TypeIndex>=$80 then
  839. Inc(Result);
  840. end;
  841. { TOmfRecord_EXTDEF }
  842. procedure TOmfRecord_EXTDEF.DecodeFrom(RawRecord: TOmfRawRecord);
  843. begin
  844. {TODO: implement}
  845. internalerror(2015040101);
  846. end;
  847. procedure TOmfRecord_EXTDEF.EncodeTo(RawRecord: TOmfRawRecord);
  848. const
  849. RecordLengthLimit = 1024;
  850. var
  851. Len,LastIncludedIndex,NextOfs,I: Integer;
  852. ExtName: TOmfExternalNameElement;
  853. begin
  854. RawRecord.RecordType:=RT_EXTDEF;
  855. NextOfs:=0;
  856. { find out how many external names can we include until we reach the length limit }
  857. Len:=NextOfs;
  858. LastIncludedIndex:=NextIndex-1;
  859. repeat
  860. Inc(LastIncludedIndex);
  861. Inc(Len,TOmfExternalNameElement(ExternalNames[LastIncludedIndex]).GetLengthInFile);
  862. until (LastIncludedIndex>=(ExternalNames.Count-1)) or ((Len+TOmfExternalNameElement(ExternalNames[LastIncludedIndex+1]).GetLengthInFile)>=RecordLengthLimit);
  863. { write the external names... }
  864. for I:=NextIndex to LastIncludedIndex do
  865. begin
  866. ExtName:=TOmfExternalNameElement(ExternalNames[I]);
  867. NextOfs:=RawRecord.WriteStringAt(NextOfs,ExtName.Name);
  868. NextOfs:=RawRecord.WriteIndexedRef(NextOfs,ExtName.TypeIndex);
  869. end;
  870. RawRecord.RecordLength:=Len+1;
  871. RawRecord.CalculateChecksumByte;
  872. { update NextIndex }
  873. NextIndex:=LastIncludedIndex+1;
  874. end;
  875. { TOmfRecord_MODEND }
  876. procedure TOmfRecord_MODEND.DecodeFrom(RawRecord: TOmfRawRecord);
  877. begin
  878. {TODO: implement}
  879. internalerror(2015040101);
  880. end;
  881. procedure TOmfRecord_MODEND.EncodeTo(RawRecord: TOmfRawRecord);
  882. var
  883. ModTyp: Byte;
  884. NextOfs: Integer;
  885. begin
  886. if Is32Bit then
  887. RawRecord.RecordType:=RT_MODEND32
  888. else
  889. RawRecord.RecordType:=RT_MODEND;
  890. ModTyp:=(Ord(IsMainModule) shl 7)+(Ord(HasStartAddress) shl 6)+(Ord(SegmentBit) shl 5)+Ord(LogicalStartAddress);
  891. RawRecord.RawData[0]:=ModTyp;
  892. NextOfs:=1;
  893. if HasStartAddress then
  894. begin
  895. {TODO: implement writing a start address}
  896. internalerror(2015040101);
  897. end;
  898. RawRecord.RecordLength:=NextOfs+1;
  899. RawRecord.CalculateChecksumByte;
  900. end;
  901. { TOmfSubRecord_FIXUP }
  902. function TOmfSubRecord_FIXUP.GetDataRecordOffset: Integer;
  903. begin
  904. Result:=FLocationOffset-FDataRecordStartOffset;
  905. end;
  906. procedure TOmfSubRecord_FIXUP.SetDataRecordOffset(AValue: Integer);
  907. begin
  908. FLocationOffset:=AValue+FDataRecordStartOffset;
  909. end;
  910. function TOmfSubRecord_FIXUP.ReadAt(RawRecord: TOmfRawRecord; Offset: Integer): Integer;
  911. var
  912. Locat: Word;
  913. FixData: Byte;
  914. begin
  915. if (Offset+2)>High(RawRecord.RawData) then
  916. internalerror(2015040504);
  917. { unlike other fields in the OMF format, this one is big endian }
  918. Locat:=(RawRecord.RawData[Offset] shl 8) or RawRecord.RawData[Offset+1];
  919. FixData:=RawRecord.RawData[Offset+2];
  920. Inc(Offset,3);
  921. if (Locat and $8000)=0 then
  922. internalerror(2015040503);
  923. DataRecordOffset:=Locat and $3FF;
  924. LocationType:=TOmfFixupLocationType((Locat shr 10) and 15);
  925. Mode:=TOmfFixupMode((Locat shr 14) and 1);
  926. FrameDeterminedByThread:=(FixData and $80)<>0;
  927. TargetDeterminedByThread:=(FixData and $08)<>0;
  928. if FrameDeterminedByThread then
  929. FrameThread:=TOmfFixupThread((FixData shr 4) and 3)
  930. else
  931. FrameMethod:=TOmfFixupFrameMethod((FixData shr 4) and 7);
  932. if TargetDeterminedByThread then
  933. begin
  934. TargetThread:=TOmfFixupThread(FixData and 3);
  935. TargetThreadDisplacementPresent:=(FixData and $40)=0;
  936. end
  937. else
  938. TargetMethod:=TOmfFixupTargetMethod(FixData and 7);
  939. { read Frame Datum? }
  940. if not FrameDeterminedByThread and (FrameMethod in [ffmSegmentIndex,ffmGroupIndex,ffmExternalIndex,ffmFrameNumber]) then
  941. Offset:=RawRecord.ReadIndexedRef(Offset,FFrameDatum)
  942. else
  943. FrameDatum:=0;
  944. { read Target Datum? }
  945. if not TargetDeterminedByThread then
  946. Offset:=RawRecord.ReadIndexedRef(Offset,FTargetDatum)
  947. else
  948. TargetDatum:=0;
  949. { read Target Displacement? }
  950. if (TargetDeterminedByThread and TargetThreadDisplacementPresent) or
  951. (TargetMethod in [ftmSegmentIndex,ftmGroupIndex,ftmExternalIndex,ftmFrameNumber]) then
  952. begin
  953. if Is32Bit then
  954. begin
  955. if (Offset+3)>High(RawRecord.RawData) then
  956. internalerror(2015040504);
  957. TargetDisplacement := RawRecord.RawData[Offset]+
  958. (RawRecord.RawData[Offset+1] shl 8)+
  959. (RawRecord.RawData[Offset+2] shl 16)+
  960. (RawRecord.RawData[Offset+3] shl 24);
  961. Inc(Offset,4);
  962. end
  963. else
  964. begin
  965. if (Offset+1)>High(RawRecord.RawData) then
  966. internalerror(2015040504);
  967. TargetDisplacement := RawRecord.RawData[Offset]+
  968. (RawRecord.RawData[Offset+1] shl 8);
  969. Inc(Offset,2);
  970. end;
  971. end;
  972. Result:=Offset;
  973. end;
  974. function TOmfSubRecord_FIXUP.WriteAt(RawRecord: TOmfRawRecord; Offset: Integer): Integer;
  975. var
  976. Locat: Word;
  977. FixData: Byte;
  978. begin
  979. if (DataRecordOffset<0) or (DataRecordOffset>1023) then
  980. internalerror(2015040501);
  981. Locat:=$8000+(Ord(Mode) shl 14)+(Ord(LocationType) shl 10)+DataRecordOffset;
  982. { unlike other fields in the OMF format, this one is big endian }
  983. RawRecord.RawData[Offset]:=Byte(Locat shr 8);
  984. RawRecord.RawData[Offset+1]:=Byte(Locat);
  985. Inc(Offset, 2);
  986. FixData:=(Ord(FrameDeterminedByThread) shl 7)+(Ord(TargetDeterminedByThread) shl 3);
  987. if FrameDeterminedByThread then
  988. FixData:=FixData+(Ord(FrameThread) shl 4)
  989. else
  990. FixData:=FixData+(Ord(FrameMethod) shl 4);
  991. if TargetDeterminedByThread then
  992. FixData:=FixData+Ord(TargetThread)+(Ord(not TargetThreadDisplacementPresent) shl 2)
  993. else
  994. FixData:=FixData+Ord(TargetMethod);
  995. RawRecord.RawData[Offset]:=FixData;
  996. Inc(Offset);
  997. { save Frame Datum? }
  998. if not FrameDeterminedByThread and (FrameMethod in [ffmSegmentIndex,ffmGroupIndex,ffmExternalIndex,ffmFrameNumber]) then
  999. Offset:=RawRecord.WriteIndexedRef(Offset,FrameDatum);
  1000. { save Target Datum? }
  1001. if not TargetDeterminedByThread then
  1002. Offset:=RawRecord.WriteIndexedRef(Offset,TargetDatum);
  1003. { save Target Displacement? }
  1004. if (TargetDeterminedByThread and TargetThreadDisplacementPresent) or
  1005. (TargetMethod in [ftmSegmentIndex,ftmGroupIndex,ftmExternalIndex,ftmFrameNumber]) then
  1006. begin
  1007. if Is32Bit then
  1008. begin
  1009. RawRecord.RawData[Offset]:=Byte(TargetDisplacement);
  1010. RawRecord.RawData[Offset+1]:=Byte(TargetDisplacement shr 8);
  1011. RawRecord.RawData[Offset+2]:=Byte(TargetDisplacement shr 16);
  1012. RawRecord.RawData[Offset+3]:=Byte(TargetDisplacement shr 24);
  1013. Inc(Offset,4);
  1014. end
  1015. else
  1016. begin
  1017. if TargetDisplacement>$ffff then
  1018. internalerror(2015040502);
  1019. RawRecord.RawData[Offset]:=Byte(TargetDisplacement);
  1020. RawRecord.RawData[Offset+1]:=Byte(TargetDisplacement shr 8);
  1021. Inc(Offset,2);
  1022. end;
  1023. end;
  1024. Result:=Offset;
  1025. end;
  1026. end.