omfbase.pas 64 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831
  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. aasmbase,
  25. owbase;
  26. const
  27. { OMF segment names for the object sections, produced by the FPC code generator }
  28. omf_secnames : array[TAsmSectiontype] of string[length('__DATA, __datacoal_nt,coalesced')] = ('','',
  29. '_TEXT',
  30. 'data',
  31. 'data',
  32. 'rodata',
  33. 'bss',
  34. 'tbss',
  35. 'pdata',
  36. '_TEXT','data','data','data','data',
  37. 'stab',
  38. 'stabstr',
  39. 'idata2','idata4','idata5','idata6','idata7','edata',
  40. 'eh_frame',
  41. 'debug_frame','debug_info','debug_line','debug_abbrev',
  42. 'fpc',
  43. '',
  44. 'init',
  45. 'fini',
  46. 'objc_class',
  47. 'objc_meta_class',
  48. 'objc_cat_cls_meth',
  49. 'objc_cat_inst_meth',
  50. 'objc_protocol',
  51. 'objc_string_object',
  52. 'objc_cls_meth',
  53. 'objc_inst_meth',
  54. 'objc_cls_refs',
  55. 'objc_message_refs',
  56. 'objc_symbols',
  57. 'objc_category',
  58. 'objc_class_vars',
  59. 'objc_instance_vars',
  60. 'objc_module_info',
  61. 'objc_class_names',
  62. 'objc_meth_var_types',
  63. 'objc_meth_var_names',
  64. 'objc_selector_strs',
  65. 'objc_protocol_ext',
  66. 'objc_class_ext',
  67. 'objc_property',
  68. 'objc_image_info',
  69. 'objc_cstring_object',
  70. 'objc_sel_fixup',
  71. '__DATA,__objc_data',
  72. '__DATA,__objc_const',
  73. 'objc_superrefs',
  74. '__DATA, __datacoal_nt,coalesced',
  75. 'objc_classlist',
  76. 'objc_nlclasslist',
  77. 'objc_catlist',
  78. 'obcj_nlcatlist',
  79. 'objc_protolist',
  80. 'stack',
  81. 'heap'
  82. );
  83. { OMF record types }
  84. RT_THEADR = $80; { Translator Header Record }
  85. RT_LHEADR = $82; { Library Module Header Record }
  86. RT_COMENT = $88; { Comment Record }
  87. RT_MODEND = $8A; { Module End Record }
  88. RT_MODEND32 = $8B;
  89. RT_EXTDEF = $8C; { External Names Definition Record }
  90. RT_PUBDEF = $90; { Public Names Definition Record }
  91. RT_PUBDEF32 = $91;
  92. RT_LINNUM = $94; { Line Numbers Record }
  93. RT_LINNUM32 = $95;
  94. RT_LNAMES = $96; { List of Names Record }
  95. RT_SEGDEF = $98; { Segment Definition Record }
  96. RT_SEGDEF32 = $99;
  97. RT_GRPDEF = $9A; { Group Definition Record }
  98. RT_FIXUPP = $9C; { Fixup Record }
  99. RT_FIXUPP32 = $9D;
  100. RT_LEDATA = $A0; { Logical Enumerated Data Record }
  101. RT_LEDATA32 = $A1;
  102. RT_LIDATA = $A2; { Logical Iterated Data Record }
  103. RT_LIDATA32 = $A3;
  104. RT_COMDEF = $B0; { Communal Names Definition Record }
  105. RT_BAKPAT = $B2; { Backpatch Record }
  106. RT_BAKPAT32 = $B3;
  107. RT_LEXTDEF = $B4; { Local External Names Definition Record }
  108. RT_LEXTDEF32 = $B5;
  109. RT_LPUBDEF = $B6; { Local Public Names Definition Record }
  110. RT_LPUBDEF32 = $B7;
  111. RT_LCOMDEF = $B8; { Local Communal Names Definition Record }
  112. RT_CEXTDEF = $BC; { COMDAT External Names Definition Record }
  113. RT_COMDAT = $C2; { Initialized Communal Data Record }
  114. RT_COMDAT32 = $C3;
  115. RT_LINSYM = $C4; { Symbol Line Numbers Record }
  116. RT_LINSYM32 = $C5;
  117. RT_ALIAS = $C6; { Alias Definition Record }
  118. RT_NBKPAT = $C8; { Named Backpatch Record }
  119. RT_NBKPAT32 = $C9;
  120. RT_LLNAMES = $CA; { Local Logical Names Definition Record }
  121. RT_VERNUM = $CC; { OMF Version Number Record }
  122. RT_VENDEXT = $CE; { Vendor-specific OMF Extension Record }
  123. RT_LIBHEAD = $F0; { Library Header Record }
  124. RT_LIBEND = $F1; { Library End Record (marks end of objects and beginning of dictionary) }
  125. { OMF comment class }
  126. CC_Translator = $00; { language translator (compiler or assembler) name }
  127. CC_IntelCopyright = $01;
  128. CC_IntelReservedRangeStart = $02;
  129. CC_IntelReservedRangeEnd = $9B;
  130. CC_LibrarySpecifierObsolete = $81;
  131. CC_MsDosVersionObsolete = $9C;
  132. CC_MemoryModel = $9D;
  133. CC_DOSSEG = $9E;
  134. CC_DefaultLibrarySearchName = $9F;
  135. CC_OmfExtension = $A0;
  136. CC_NewOmfExtension = $A1;
  137. CC_LinkPassSeparator = $A2;
  138. CC_LIBMOD = $A3;
  139. CC_EXESTR = $A4;
  140. CC_INCERR = $A6;
  141. CC_NOPAD = $A7;
  142. CC_WKEXT = $A8;
  143. CC_LZEXT = $A9;
  144. CC_Comment = $DA;
  145. CC_Compiler = $DB;
  146. CC_Date = $DC;
  147. CC_Timestamp = $DD;
  148. CC_User = $DF;
  149. CC_DependencyFileBorland = $E9;
  150. CC_CommandLineMicrosoft = $FF;
  151. type
  152. TOmfSegmentAlignment = (
  153. saAbsolute = 0,
  154. saRelocatableByteAligned = 1,
  155. saRelocatableWordAligned = 2,
  156. saRelocatableParaAligned = 3,
  157. saRelocatablePageAligned = 4, { 32-bit linkers extension }
  158. saRelocatableDWordAligned = 5, { 32-bit linkers extension }
  159. saNotSupported = 6,
  160. saNotDefined = 7);
  161. TOmfSegmentCombination = (
  162. scPrivate = 0,
  163. scReserved1 = 1,
  164. scPublic = 2,
  165. scReserved3 = 3,
  166. scPublic4 = 4, { same as scPublic }
  167. scStack = 5,
  168. scCommon = 6,
  169. scPublic7 = 7); { same as scPublic }
  170. TOmfSegmentUse = (suUse16, suUse32);
  171. TOmfFixupThread = (ftThread0, ftThread1, ftThread2, ftThread3);
  172. TOmfFixupMode = (fmSelfRelative, fmSegmentRelative);
  173. TOmfFixupLocationType = (
  174. fltLoByte = 0, { low 8 bits of 16-bit offset }
  175. fltOffset = 1, { 16-bit offset }
  176. fltBase = 2, { 16-bit base (segment) }
  177. fltFarPointer = 3, { 16-bit base:16-bit offset }
  178. fltHiByte = 4, { high 8 bits of 16-bit offset }
  179. fltLoaderResolvedOffset = 5, { PharLap: Offset32 }
  180. fltUndefined6 = 6, { PharLap: Pointer48 }
  181. fltUndefined7 = 7,
  182. fltUndefined8 = 8,
  183. fltOffset32 = 9, { 32-bit offset }
  184. fltUndefined10 = 10,
  185. fltFarPointer48 = 11, { 16-bit base:32-bit offset }
  186. fltUndefined12 = 12,
  187. fltLoaderResolvedOffset32 = 13,
  188. fltUndefined14 = 14,
  189. fltUndefined15 = 15);
  190. TOmfFixupFrameMethod = (
  191. ffmSegmentIndex = 0, { SI(<segment name>) - The frame is the canonic frame of the logical
  192. segment segment defined by the index }
  193. ffmGroupIndex = 1, { GI(<group name>) - The frame is the canonic frame of the group
  194. (= the canonic frame of the logical segment from the group,
  195. located at the lowest memory address) }
  196. ffmExternalIndex = 2, { EI(<symbol name>) - The frame is determined depending on the external's public definition:
  197. * if the symbol is defined relative to a logical segment and no defined group,
  198. the frame of the logical segment is used
  199. * if the symbol is defined absolutely, without reference to a logical segment and
  200. no defined group, the FRAME NUMBER from the symbol's PUBDEF record is used
  201. * regardless of how the symbol is specified, if there's an associated group,
  202. that group's canonic frame is used }
  203. ffmFrameNumber = 3, { <FRAME NUMBER> - The frame is a directly specified constant. }
  204. ffmLocation = 4, { LOCATION - The frame is determined by the location (i.e. the canonic frame of the logical
  205. segment where the fixup location is) }
  206. ffmTarget = 5, { TARGET - The frame is determined by the target. }
  207. ffmNone = 6, { NONE - There is no frame. Used for 8089 self-relative references. }
  208. ffmUndefined = 7);
  209. TOmfFixupTargetMethod = (
  210. ftmSegmentIndex = 0, { SI(<segment name>),<displacement> }
  211. ftmGroupIndex = 1, { GI(<group name>),<displacement> }
  212. ftmExternalIndex = 2, { EI(<symbol name>),<displacement> }
  213. ftmFrameNumber = 3, { <FRAME NUMBER>,<displacement> }
  214. ftmSegmentIndexNoDisp = 4, { SI(<segment name>) }
  215. ftmGroupIndexNoDisp = 5, { GI(<group name>) }
  216. ftmExternalIndexNoDisp = 6, { EI(<symbol name>) }
  217. ftmFrameNumberNoDisp = 7); { <FRAME NUMBER> }
  218. { TOmfOrderedNameCollection }
  219. TOmfOrderedNameCollection = class
  220. private
  221. FStringList: array of string;
  222. function GetCount: Integer;
  223. function GetString(Index: Integer): string;
  224. procedure SetString(Index: Integer; AValue: string);
  225. public
  226. function Add(const S: string): Integer;
  227. procedure Clear;
  228. property Strings [Index: Integer]: string read GetString write SetString; default;
  229. property Count: Integer read GetCount;
  230. end;
  231. { TOmfRawRecord }
  232. TOmfRawRecord = class
  233. private
  234. function GetChecksumByte: Byte;
  235. function GetRecordLength: Word;
  236. function GetRecordType: Byte;
  237. procedure SetChecksumByte(AValue: Byte);
  238. procedure SetRecordLength(AValue: Word);
  239. procedure SetRecordType(AValue: Byte);
  240. public
  241. RawData: array [-3..65535] of Byte;
  242. property RecordType: Byte read GetRecordType write SetRecordType;
  243. property RecordLength: Word read GetRecordLength write SetRecordLength;
  244. function ReadStringAt(Offset: Integer; out s: string): Integer;
  245. function WriteStringAt(Offset: Integer; s: string): Integer;
  246. function ReadIndexedRef(Offset: Integer; out IndexedRef: Integer): Integer;
  247. function WriteIndexedRef(Offset: Integer; IndexedRef: Integer): Integer;
  248. procedure CalculateChecksumByte;
  249. function VerifyChecksumByte: boolean;
  250. property ChecksumByte: Byte read GetChecksumByte write SetChecksumByte;
  251. procedure ReadFrom(aReader: TObjectReader);
  252. procedure ReadFrom(aReader: TDynamicArray);
  253. procedure WriteTo(aWriter: TObjectWriter);
  254. procedure WriteTo(aWriter: TDynamicArray);
  255. end;
  256. { TOmfParsedRecord }
  257. TOmfParsedRecord = class
  258. public
  259. procedure DecodeFrom(RawRecord: TOmfRawRecord);virtual;abstract;
  260. procedure EncodeTo(RawRecord: TOmfRawRecord);virtual;abstract;
  261. end;
  262. { TOmfRecord_THEADR }
  263. TOmfRecord_THEADR = class(TOmfParsedRecord)
  264. private
  265. FModuleName: string;
  266. public
  267. procedure DecodeFrom(RawRecord: TOmfRawRecord);override;
  268. procedure EncodeTo(RawRecord: TOmfRawRecord);override;
  269. property ModuleName: string read FModuleName write FModuleName;
  270. end;
  271. { TOmfRecord_COMENT }
  272. TOmfRecord_COMENT = class(TOmfParsedRecord)
  273. private
  274. FCommentType: Byte;
  275. FCommentClass: Byte;
  276. FCommentString: string;
  277. function GetNoList: Boolean;
  278. function GetNoPurge: Boolean;
  279. procedure SetNoList(AValue: Boolean);
  280. procedure SetNoPurge(AValue: Boolean);
  281. public
  282. procedure DecodeFrom(RawRecord: TOmfRawRecord);override;
  283. procedure EncodeTo(RawRecord: TOmfRawRecord);override;
  284. property CommentType: Byte read FCommentType write FCommentType;
  285. property CommentClass: Byte read FCommentClass write FCommentClass;
  286. property CommentString: string read FCommentString write FCommentString;
  287. property NoPurge: Boolean read GetNoPurge write SetNoPurge;
  288. property NoList: Boolean read GetNoList write SetNoList;
  289. end;
  290. { TOmfRecord_LNAMES }
  291. TOmfRecord_LNAMES = class(TOmfParsedRecord)
  292. private
  293. FNames: TOmfOrderedNameCollection;
  294. FNextIndex: Integer;
  295. public
  296. constructor Create;
  297. procedure DecodeFrom(RawRecord: TOmfRawRecord);override;
  298. procedure EncodeTo(RawRecord: TOmfRawRecord);override;
  299. property Names: TOmfOrderedNameCollection read FNames write FNames;
  300. property NextIndex: Integer read FNextIndex write FNextIndex;
  301. end;
  302. { TOmfRecord_SEGDEF }
  303. TOmfRecord_SEGDEF = class(TOmfParsedRecord)
  304. private
  305. FAlignment: TOmfSegmentAlignment;
  306. FCombination: TOmfSegmentCombination;
  307. FUse: TOmfSegmentUse;
  308. FFrameNumber: Word;
  309. FOffset: Byte;
  310. FIs32Bit: Boolean;
  311. FSegmentLength: Int64; { int64, because it can be 2**32 }
  312. FSegmentNameIndex: Integer;
  313. FClassNameIndex: Integer;
  314. FOverlayNameIndex: Integer;
  315. public
  316. procedure DecodeFrom(RawRecord: TOmfRawRecord);override;
  317. procedure EncodeTo(RawRecord: TOmfRawRecord);override;
  318. property Alignment: TOmfSegmentAlignment read FAlignment write FAlignment;
  319. property Combination: TOmfSegmentCombination read FCombination write FCombination;
  320. property Use: TOmfSegmentUse read FUse write FUse;
  321. property FrameNumber: Word read FFrameNumber write FFrameNumber;
  322. property Offset: Byte read FOffset write FOffset;
  323. property Is32Bit: Boolean read FIs32Bit write FIs32Bit;
  324. property SegmentLength: Int64 read FSegmentLength write FSegmentLength;
  325. property SegmentNameIndex: Integer read FSegmentNameIndex write FSegmentNameIndex;
  326. property ClassNameIndex: Integer read FClassNameIndex write FClassNameIndex;
  327. property OverlayNameIndex: Integer read FOverlayNameIndex write FOverlayNameIndex;
  328. end;
  329. TSegmentList = array of Integer;
  330. { TOmfRecord_GRPDEF }
  331. TOmfRecord_GRPDEF = class(TOmfParsedRecord)
  332. private
  333. FGroupNameIndex: Integer;
  334. FSegmentList: TSegmentList;
  335. public
  336. procedure DecodeFrom(RawRecord: TOmfRawRecord);override;
  337. procedure EncodeTo(RawRecord: TOmfRawRecord);override;
  338. property GroupNameIndex: Integer read FGroupNameIndex write FGroupNameIndex;
  339. property SegmentList: TSegmentList read FSegmentList write FSegmentList;
  340. end;
  341. { TOmfPublicNameElement }
  342. TOmfPublicNameElement = class(TFPHashObject)
  343. private
  344. FPublicOffset: DWord;
  345. FTypeIndex: Integer;
  346. public
  347. function GetLengthInFile(Is32Bit: Boolean): Integer;
  348. property PublicOffset: DWord read FPublicOffset write FPublicOffset;
  349. property TypeIndex: Integer read FTypeIndex write FTypeIndex;
  350. end;
  351. { TOmfRecord_PUBDEF }
  352. TOmfRecord_PUBDEF = class(TOmfParsedRecord)
  353. private
  354. FIs32Bit: Boolean;
  355. FBaseGroupIndex: Integer;
  356. FBaseSegmentIndex: Integer;
  357. FBaseFrame: Word;
  358. FPublicNames: TFPHashObjectList;
  359. FNextIndex: Integer;
  360. public
  361. procedure DecodeFrom(RawRecord: TOmfRawRecord);override;
  362. procedure EncodeTo(RawRecord: TOmfRawRecord);override;
  363. property Is32Bit: Boolean read FIs32Bit write FIs32Bit;
  364. property BaseGroupIndex: Integer read FBaseGroupIndex write FBaseGroupIndex;
  365. property BaseSegmentIndex: Integer read FBaseSegmentIndex write FBaseSegmentIndex;
  366. property BaseFrame: Word read FBaseFrame write FBaseFrame;
  367. property PublicNames: TFPHashObjectList read FPublicNames write FPublicNames;
  368. property NextIndex: Integer read FNextIndex write FNextIndex;
  369. end;
  370. { TOmfExternalNameElement }
  371. TOmfExternalNameElement = class(TFPHashObject)
  372. private
  373. FTypeIndex: Integer;
  374. public
  375. function GetLengthInFile: Integer;
  376. property TypeIndex: Integer read FTypeIndex write FTypeIndex;
  377. end;
  378. { TOmfRecord_EXTDEF }
  379. TOmfRecord_EXTDEF = class(TOmfParsedRecord)
  380. private
  381. FExternalNames: TFPHashObjectList;
  382. FNextIndex: Integer;
  383. public
  384. procedure DecodeFrom(RawRecord: TOmfRawRecord);override;
  385. procedure EncodeTo(RawRecord: TOmfRawRecord);override;
  386. property ExternalNames: TFPHashObjectList read FExternalNames write FExternalNames;
  387. property NextIndex: Integer read FNextIndex write FNextIndex;
  388. end;
  389. { TOmfRecord_MODEND }
  390. TOmfRecord_MODEND = class(TOmfParsedRecord)
  391. private
  392. FIs32Bit: Boolean;
  393. FIsMainModule: Boolean;
  394. FHasStartAddress: Boolean;
  395. FSegmentBit: Boolean;
  396. FLogicalStartAddress: Boolean;
  397. FFrameMethod: TOmfFixupFrameMethod;
  398. FFrameDatum: Integer;
  399. FTargetMethod: TOmfFixupTargetMethod;
  400. FTargetDatum: Integer;
  401. FTargetDisplacement: DWord;
  402. FPhysFrameNumber: Word;
  403. FPhysOffset: DWord;
  404. public
  405. procedure DecodeFrom(RawRecord: TOmfRawRecord);override;
  406. procedure EncodeTo(RawRecord: TOmfRawRecord);override;
  407. property Is32Bit: Boolean read FIs32Bit write FIs32Bit;
  408. property IsMainModule: Boolean read FIsMainModule write FIsMainModule;
  409. property HasStartAddress: Boolean read FHasStartAddress write FHasStartAddress;
  410. property SegmentBit: Boolean read FSegmentBit write FSegmentBit;
  411. property LogicalStartAddress: Boolean read FLogicalStartAddress write FLogicalStartAddress;
  412. { properties, specifying a logical start address (used when LogicalStartAddress=true) }
  413. property FrameMethod: TOmfFixupFrameMethod read FFrameMethod write FFrameMethod;
  414. property FrameDatum: Integer read FFrameDatum write FFrameDatum;
  415. property TargetMethod: TOmfFixupTargetMethod read FTargetMethod write FTargetMethod;
  416. property TargetDatum: Integer read FTargetDatum write FTargetDatum;
  417. property TargetDisplacement: DWord read FTargetDisplacement write FTargetDisplacement;
  418. { properties, specifying a physical start address (used when LogicalStartAddress=false) }
  419. property PhysFrameNumber: Word read FPhysFrameNumber write FPhysFrameNumber;
  420. property PhysOffset: DWord read FPhysOffset write FPhysOffset;
  421. end;
  422. { TOmfSubRecord_FIXUP }
  423. TOmfSubRecord_FIXUP = class
  424. private
  425. FIs32Bit: Boolean;
  426. FMode: TOmfFixupMode;
  427. FLocationType: TOmfFixupLocationType;
  428. FLocationOffset: DWord;
  429. FDataRecordStartOffset: DWord;
  430. FTargetDeterminedByThread: Boolean;
  431. FTargetThread: TOmfFixupThread;
  432. FTargetThreadDisplacementPresent: Boolean;
  433. FTargetMethod: TOmfFixupTargetMethod;
  434. FTargetDatum: Integer;
  435. FTargetDisplacement: DWord;
  436. FFrameDeterminedByThread: Boolean;
  437. FFrameThread: TOmfFixupThread;
  438. FFrameMethod: TOmfFixupFrameMethod;
  439. FFrameDatum: Integer;
  440. function GetDataRecordOffset: Integer;
  441. function GetLocationSize: Integer;
  442. procedure SetDataRecordOffset(AValue: Integer);
  443. public
  444. function ReadAt(RawRecord: TOmfRawRecord; Offset: Integer): Integer;
  445. function WriteAt(RawRecord: TOmfRawRecord; Offset: Integer): Integer;
  446. property Is32Bit: Boolean read FIs32Bit write FIs32Bit;
  447. property Mode: TOmfFixupMode read FMode write FMode;
  448. property LocationType: TOmfFixupLocationType read FLocationType write FLocationType;
  449. property LocationOffset: DWord read FLocationOffset write FLocationOffset;
  450. property LocationSize: Integer read GetLocationSize;
  451. property DataRecordStartOffset: DWord read FDataRecordStartOffset write FDataRecordStartOffset;
  452. property DataRecordOffset: Integer read GetDataRecordOffset write SetDataRecordOffset;
  453. property TargetDeterminedByThread: Boolean read FTargetDeterminedByThread write FTargetDeterminedByThread;
  454. property TargetThread: TOmfFixupThread read FTargetThread write FTargetThread;
  455. property TargetThreadDisplacementPresent: Boolean read FTargetThreadDisplacementPresent write FTargetThreadDisplacementPresent;
  456. property TargetMethod: TOmfFixupTargetMethod read FTargetMethod write FTargetMethod;
  457. property TargetDatum: Integer read FTargetDatum write FTargetDatum;
  458. property TargetDisplacement: DWord read FTargetDisplacement write FTargetDisplacement;
  459. property FrameDeterminedByThread: Boolean read FFrameDeterminedByThread write FFrameDeterminedByThread;
  460. property FrameThread: TOmfFixupThread read FFrameThread write FFrameThread;
  461. property FrameMethod: TOmfFixupFrameMethod read FFrameMethod write FFrameMethod;
  462. property FrameDatum: Integer read FFrameDatum write FFrameDatum;
  463. end;
  464. { TOmfRecord_LIBHEAD }
  465. TOmfRecord_LIBHEAD = class(TOmfParsedRecord)
  466. private
  467. FPageSize: Integer;
  468. FDictionaryOffset: DWord;
  469. FDictionarySizeInBlocks: Word;
  470. FFlags: Byte;
  471. function IsCaseSensitive: Boolean;
  472. procedure SetCaseSensitive(AValue: Boolean);
  473. procedure SetPageSize(AValue: Integer);
  474. public
  475. constructor Create;
  476. procedure DecodeFrom(RawRecord: TOmfRawRecord);override;
  477. procedure EncodeTo(RawRecord: TOmfRawRecord);override;
  478. property PageSize: Integer read FPageSize write SetPageSize;
  479. property DictionaryOffset: DWord read FDictionaryOffset write FDictionaryOffset;
  480. property DictionarySizeInBlocks: Word read FDictionarySizeInBlocks write FDictionarySizeInBlocks;
  481. property Flags: Byte read FFlags write FFlags;
  482. property CaseSensitive: Boolean read IsCaseSensitive write SetCaseSensitive;
  483. end;
  484. { TOmfRecord_LIBEND }
  485. TOmfRecord_LIBEND = class(TOmfParsedRecord)
  486. private
  487. FPaddingBytes: Word;
  488. public
  489. procedure DecodeFrom(RawRecord: TOmfRawRecord);override;
  490. procedure EncodeTo(RawRecord: TOmfRawRecord);override;
  491. procedure CalculatePaddingBytes(RecordStartOffset: DWord);
  492. property PaddingBytes: Word read FPaddingBytes write FPaddingBytes;
  493. end;
  494. const
  495. { list of all the possible omf library dictionary block counts - contains
  496. all the prime numbers less than 255 }
  497. OmfLibDictionaryBlockCounts: array [0..53] of Byte =
  498. (2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,
  499. 101,103,107,109,113,127,131,137,139,149,151,157,163,167,173,179,181,191,
  500. 193,197,199,211,223,227,229,233,239,241,251);
  501. type
  502. TOmfLibHash = record
  503. block_x: Integer;
  504. block_d: Integer;
  505. bucket_x: Integer;
  506. bucket_d: Integer;
  507. end;
  508. function compute_omf_lib_hash(const name: string; blocks: Integer): TOmfLibHash;
  509. { OMF segment class names for the object sections, produced by the FPC code generator }
  510. function omf_segclass(atype:TAsmSectiontype):string;
  511. function omf_sectiontype2align(atype:TAsmSectiontype):shortint;
  512. { returns whether the specified section type belongs to the group DGROUP in
  513. the current memory model. DGROUP is the segment group pointed by DS }
  514. function section_belongs_to_dgroup(atype:TAsmSectiontype): Boolean;
  515. implementation
  516. uses
  517. cutils,
  518. globals,globtype,
  519. verbose,
  520. cpuinfo;
  521. { TOmfOrderedNameCollection }
  522. function TOmfOrderedNameCollection.GetString(Index: Integer): string;
  523. begin
  524. Result:=FStringList[Index-1];
  525. end;
  526. function TOmfOrderedNameCollection.GetCount: Integer;
  527. begin
  528. Result:=Length(FStringList);
  529. end;
  530. procedure TOmfOrderedNameCollection.SetString(Index: Integer; AValue: string);
  531. begin
  532. FStringList[Index-1]:=AValue;
  533. end;
  534. function TOmfOrderedNameCollection.Add(const S: string): Integer;
  535. begin
  536. Result:=Length(FStringList)+1;
  537. SetLength(FStringList,Result);
  538. FStringList[Result-1]:=S;
  539. end;
  540. procedure TOmfOrderedNameCollection.Clear;
  541. begin
  542. SetLength(FStringList,0);
  543. end;
  544. { TOmfRawRecord }
  545. function TOmfRawRecord.GetRecordType: Byte;
  546. begin
  547. Result:=RawData[-3];
  548. end;
  549. procedure TOmfRawRecord.SetRecordType(AValue: Byte);
  550. begin
  551. RawData[-3]:=AValue;
  552. end;
  553. function TOmfRawRecord.GetRecordLength: Word;
  554. begin
  555. Result:=RawData[-2] or (RawData[-1] shl 8);
  556. end;
  557. procedure TOmfRawRecord.SetRecordLength(AValue: Word);
  558. begin
  559. RawData[-2]:=Byte(AValue);
  560. RawData[-1]:=Byte(AValue shr 8);
  561. end;
  562. function TOmfRawRecord.ReadStringAt(Offset: Integer; out s: string): Integer;
  563. var
  564. len: Byte;
  565. begin
  566. len:=RawData[Offset];
  567. Result:=Offset+len+1;
  568. if result>RecordLength then
  569. internalerror(2015033103);
  570. SetLength(s, len);
  571. UniqueString(s);
  572. Move(RawData[Offset+1],s[1],len);
  573. end;
  574. function TOmfRawRecord.WriteStringAt(Offset: Integer; s: string): Integer;
  575. begin
  576. if Length(s)>255 then
  577. internalerror(2015033101);
  578. result:=Offset+Length(s)+1;
  579. if result>High(RawData) then
  580. internalerror(2015033102);
  581. RawData[Offset]:=Length(s);
  582. Move(s[1], RawData[Offset+1], Length(s));
  583. end;
  584. function TOmfRawRecord.ReadIndexedRef(Offset: Integer; out IndexedRef: Integer): Integer;
  585. begin
  586. Result:=Offset+1;
  587. if result>RecordLength then
  588. internalerror(2015033103);
  589. IndexedRef:=RawData[Offset];
  590. if IndexedRef<=$7f then
  591. exit;
  592. Result:=Offset+2;
  593. if result>RecordLength then
  594. internalerror(2015033103);
  595. IndexedRef:=((IndexedRef and $7f) shl 8)+RawData[Offset+1];
  596. end;
  597. function TOmfRawRecord.WriteIndexedRef(Offset: Integer; IndexedRef: Integer): Integer;
  598. begin
  599. if (IndexedRef<0) or (IndexedRef>$7FFF) then
  600. internalerror(2015040303);
  601. if IndexedRef<=$7f then
  602. begin
  603. Result:=Offset+1;
  604. if Result>High(RawData) then
  605. internalerror(2015033102);
  606. RawData[Offset]:=IndexedRef;
  607. end
  608. else
  609. begin
  610. Result:=Offset+2;
  611. if Result>High(RawData) then
  612. internalerror(2015033102);
  613. RawData[Offset]:=$80+(IndexedRef shr 8);
  614. RawData[Offset+1]:=Byte(IndexedRef);
  615. end;
  616. end;
  617. function TOmfRawRecord.GetChecksumByte: Byte;
  618. begin
  619. if RecordLength>0 then
  620. Result:=RawData[RecordLength-1]
  621. else
  622. Result:=0;
  623. end;
  624. procedure TOmfRawRecord.SetChecksumByte(AValue: Byte);
  625. begin
  626. if RecordLength>0 then
  627. RawData[RecordLength-1]:=AValue;
  628. end;
  629. procedure TOmfRawRecord.CalculateChecksumByte;
  630. var
  631. I: Integer;
  632. b: Byte;
  633. begin
  634. b:=0;
  635. for I:=-3 to RecordLength-2 do
  636. b:=byte(b+RawData[I]);
  637. SetChecksumByte($100-b);
  638. end;
  639. function TOmfRawRecord.VerifyChecksumByte: boolean;
  640. var
  641. I: Integer;
  642. b: Byte;
  643. begin
  644. { according to the OMF spec, some tools always write a 0 rather than
  645. computing the checksum, so it should also be accepted as correct }
  646. if ChecksumByte=0 then
  647. exit(true);
  648. b:=0;
  649. for I:=-3 to RecordLength-1 do
  650. b:=byte(b+RawData[I]);
  651. Result:=(b=0);
  652. end;
  653. procedure TOmfRawRecord.ReadFrom(aReader: TObjectReader);
  654. begin
  655. aReader.read(RawData, 3);
  656. aReader.read(RawData[0], RecordLength);
  657. end;
  658. procedure TOmfRawRecord.ReadFrom(aReader: TDynamicArray);
  659. begin
  660. aReader.read(RawData, 3);
  661. aReader.read(RawData[0], RecordLength);
  662. end;
  663. procedure TOmfRawRecord.WriteTo(aWriter: TObjectWriter);
  664. begin
  665. aWriter.write(RawData, RecordLength+3);
  666. end;
  667. procedure TOmfRawRecord.WriteTo(aWriter: TDynamicArray);
  668. begin
  669. aWriter.write(RawData, RecordLength+3);
  670. end;
  671. { TOmfRecord_THEADR }
  672. procedure TOmfRecord_THEADR.DecodeFrom(RawRecord: TOmfRawRecord);
  673. begin
  674. if RawRecord.RecordType<>RT_THEADR then
  675. internalerror(2015040301);
  676. RawRecord.ReadStringAt(0,FModuleName);
  677. end;
  678. procedure TOmfRecord_THEADR.EncodeTo(RawRecord: TOmfRawRecord);
  679. var
  680. NextOfs: Integer;
  681. begin
  682. RawRecord.RecordType:=RT_THEADR;
  683. NextOfs:=RawRecord.WriteStringAt(0,ModuleName);
  684. RawRecord.RecordLength:=NextOfs+1;
  685. RawRecord.CalculateChecksumByte;
  686. end;
  687. { TOmfRecord_COMENT }
  688. function TOmfRecord_COMENT.GetNoList: Boolean;
  689. begin
  690. Result:=(CommentType and $40)<>0;
  691. end;
  692. function TOmfRecord_COMENT.GetNoPurge: Boolean;
  693. begin
  694. Result:=(CommentType and $80)<>0;
  695. end;
  696. procedure TOmfRecord_COMENT.SetNoList(AValue: Boolean);
  697. begin
  698. if AValue then
  699. CommentType:=CommentType or $40
  700. else
  701. CommentType:=CommentType and $BF;
  702. end;
  703. procedure TOmfRecord_COMENT.SetNoPurge(AValue: Boolean);
  704. begin
  705. if AValue then
  706. CommentType:=CommentType or $80
  707. else
  708. CommentType:=CommentType and $7F;
  709. end;
  710. procedure TOmfRecord_COMENT.DecodeFrom(RawRecord: TOmfRawRecord);
  711. begin
  712. if RawRecord.RecordType<>RT_COMENT then
  713. internalerror(2015040301);
  714. if RawRecord.RecordLength<3 then
  715. internalerror(2015033104);
  716. CommentType:=RawRecord.RawData[0];
  717. CommentClass:=RawRecord.RawData[1];
  718. SetLength(FCommentString,RawRecord.RecordLength-3);
  719. UniqueString(FCommentString);
  720. Move(RawRecord.RawData[2],FCommentString[1],Length(FCommentString));
  721. end;
  722. procedure TOmfRecord_COMENT.EncodeTo(RawRecord: TOmfRawRecord);
  723. begin
  724. RawRecord.RecordType:=RT_COMENT;
  725. if (Length(FCommentString)+3)>High(RawRecord.RawData) then
  726. internalerror(2015033105);
  727. RawRecord.RecordLength:=Length(FCommentString)+3;
  728. RawRecord.RawData[0]:=CommentType;
  729. RawRecord.RawData[1]:=CommentClass;
  730. Move(FCommentString[1],RawRecord.RawData[2],Length(FCommentString));
  731. RawRecord.CalculateChecksumByte;
  732. end;
  733. { TOmfRecord_LNAMES }
  734. constructor TOmfRecord_LNAMES.Create;
  735. begin
  736. FNextIndex:=1;
  737. end;
  738. procedure TOmfRecord_LNAMES.DecodeFrom(RawRecord: TOmfRawRecord);
  739. var
  740. NextOfs: Integer;
  741. Name: string;
  742. begin
  743. if RawRecord.RecordType<>RT_LNAMES then
  744. internalerror(2015040301);
  745. NextOfs:=0;
  746. while NextOfs<(RawRecord.RecordLength-1) do
  747. begin
  748. NextOfs:=RawRecord.ReadStringAt(NextOfs,Name);
  749. Names.Add(Name);
  750. end;
  751. end;
  752. procedure TOmfRecord_LNAMES.EncodeTo(RawRecord: TOmfRawRecord);
  753. const
  754. RecordLengthLimit = 1024;
  755. var
  756. Len,LastIncludedIndex,NextOfs,I: Integer;
  757. begin
  758. RawRecord.RecordType:=RT_LNAMES;
  759. { find out how many strings can we include until we reach the length limit }
  760. Len:=1;
  761. LastIncludedIndex:=NextIndex-1;
  762. repeat
  763. Inc(LastIncludedIndex);
  764. Inc(Len,Length(Names[LastIncludedIndex])+1);
  765. until (LastIncludedIndex>=Names.Count) or ((Len+Length(Names[LastIncludedIndex+1])+1)>=RecordLengthLimit);
  766. { write the strings... }
  767. NextOfs:=0;
  768. for I:=NextIndex to LastIncludedIndex do
  769. NextOfs:=RawRecord.WriteStringAt(NextOfs,Names[I]);
  770. RawRecord.RecordLength:=Len;
  771. RawRecord.CalculateChecksumByte;
  772. { update NextIndex }
  773. NextIndex:=LastIncludedIndex+1;
  774. end;
  775. { TOmfRecord_SEGDEF }
  776. procedure TOmfRecord_SEGDEF.DecodeFrom(RawRecord: TOmfRawRecord);
  777. var
  778. B: Byte;
  779. Big: Boolean;
  780. NextOfs: Integer;
  781. MinLen: Integer;
  782. begin
  783. if not (RawRecord.RecordType in [RT_SEGDEF,RT_SEGDEF32]) then
  784. internalerror(2015040301);
  785. Is32Bit:=RawRecord.RecordType=RT_SEGDEF32;
  786. MinLen:=7; { b(1)+seglength(2..4)+segnameindex(1..2)+classnameindex(1..2)+overlaynameindex(1..2)+checksum }
  787. if Is32Bit then
  788. inc(MinLen,2);
  789. if RawRecord.RecordLength<MinLen then
  790. internalerror(2015040305);
  791. B:=RawRecord.RawData[0];
  792. Alignment:=TOmfSegmentAlignment(B shr 5);
  793. Combination:=TOmfSegmentCombination((B shr 2) and 7);
  794. Big:=(B and 2)<>0;
  795. Use:=TOmfSegmentUse(B and 1);
  796. NextOfs:=1;
  797. if Alignment=saAbsolute then
  798. begin
  799. inc(MinLen,3);
  800. if RawRecord.RecordLength<MinLen then
  801. internalerror(2015040305);
  802. FrameNumber:=RawRecord.RawData[1]+(RawRecord.RawData[2] shl 8);
  803. Offset:=RawRecord.RawData[3];
  804. NextOfs:=4;
  805. end
  806. else
  807. begin
  808. FrameNumber:=0;
  809. Offset:=0;
  810. end;
  811. if Is32Bit then
  812. begin
  813. SegmentLength:=RawRecord.RawData[NextOfs]+
  814. (RawRecord.RawData[NextOfs+1] shl 8)+
  815. (RawRecord.RawData[NextOfs+2] shl 16)+
  816. (RawRecord.RawData[NextOfs+3] shl 24);
  817. if Big then
  818. if SegmentLength=0 then
  819. SegmentLength:=4294967296
  820. else
  821. internalerror(2015040306);
  822. Inc(NextOfs,4);
  823. end
  824. else
  825. begin
  826. SegmentLength:=RawRecord.RawData[NextOfs]+(RawRecord.RawData[NextOfs+1] shl 8);
  827. if Big then
  828. if SegmentLength=0 then
  829. SegmentLength:=65536
  830. else
  831. internalerror(2015040306);
  832. Inc(NextOfs,2);
  833. end;
  834. NextOfs:=RawRecord.ReadIndexedRef(NextOfs,FSegmentNameIndex);
  835. NextOfs:=RawRecord.ReadIndexedRef(NextOfs,FClassNameIndex);
  836. NextOfs:=RawRecord.ReadIndexedRef(NextOfs,FOverlayNameIndex);
  837. end;
  838. procedure TOmfRecord_SEGDEF.EncodeTo(RawRecord: TOmfRawRecord);
  839. var
  840. Big: Boolean;
  841. NextOfs: Integer;
  842. begin
  843. if Is32Bit then
  844. begin
  845. RawRecord.RecordType:=RT_SEGDEF32;
  846. if SegmentLength>4294967296 then
  847. internalerror(2015040302);
  848. Big:=SegmentLength=4294967296;
  849. end
  850. else
  851. begin
  852. RawRecord.RecordType:=RT_SEGDEF;
  853. if SegmentLength>65536 then
  854. internalerror(2015040302);
  855. Big:=SegmentLength=65536;
  856. end;
  857. RawRecord.RawData[0]:=(Ord(Alignment) shl 5) or (Ord(Combination) shl 2) or (Ord(Big) shl 1) or Ord(Use);
  858. NextOfs:=1;
  859. if Alignment=saAbsolute then
  860. begin
  861. RawRecord.RawData[1]:=Byte(FrameNumber);
  862. RawRecord.RawData[2]:=Byte(FrameNumber shr 8);
  863. RawRecord.RawData[3]:=Offset;
  864. NextOfs:=4;
  865. end;
  866. if Is32Bit then
  867. begin
  868. RawRecord.RawData[NextOfs]:=Byte(SegmentLength);
  869. RawRecord.RawData[NextOfs+1]:=Byte(SegmentLength shr 8);
  870. RawRecord.RawData[NextOfs+2]:=Byte(SegmentLength shr 16);
  871. RawRecord.RawData[NextOfs+3]:=Byte(SegmentLength shr 24);
  872. Inc(NextOfs,4);
  873. end
  874. else
  875. begin
  876. RawRecord.RawData[NextOfs]:=Byte(SegmentLength);
  877. RawRecord.RawData[NextOfs+1]:=Byte(SegmentLength shr 8);
  878. Inc(NextOfs,2);
  879. end;
  880. NextOfs:=RawRecord.WriteIndexedRef(NextOfs,SegmentNameIndex);
  881. NextOfs:=RawRecord.WriteIndexedRef(NextOfs,ClassNameIndex);
  882. NextOfs:=RawRecord.WriteIndexedRef(NextOfs,OverlayNameIndex);
  883. RawRecord.RecordLength:=NextOfs+1;
  884. RawRecord.CalculateChecksumByte;
  885. end;
  886. { TOmfRecord_GRPDEF }
  887. procedure TOmfRecord_GRPDEF.DecodeFrom(RawRecord: TOmfRawRecord);
  888. var
  889. NextOfs: Integer;
  890. Segment: Integer;
  891. begin
  892. if RawRecord.RecordType<>RT_GRPDEF then
  893. internalerror(2015040301);
  894. NextOfs:=RawRecord.ReadIndexedRef(0,FGroupNameIndex);
  895. SetLength(FSegmentList,0);
  896. while NextOfs<RawRecord.RecordLength-1 do
  897. begin
  898. if RawRecord.RawData[NextOfs]<>$ff then
  899. internalerror(2015040901);
  900. NextOfs:=RawRecord.ReadIndexedRef(NextOfs+1,Segment);
  901. SetLength(FSegmentList,Length(FSegmentList)+1);
  902. FSegmentList[High(FSegmentList)]:=Segment;
  903. end;
  904. end;
  905. procedure TOmfRecord_GRPDEF.EncodeTo(RawRecord: TOmfRawRecord);
  906. var
  907. NextOfs: Integer;
  908. Segment: Integer;
  909. begin
  910. RawRecord.RecordType:=RT_GRPDEF;
  911. NextOfs:=RawRecord.WriteIndexedRef(0,GroupNameIndex);
  912. for Segment in SegmentList do
  913. begin
  914. if NextOfs>High(RawRecord.RawData) then
  915. internalerror(2015040401);
  916. RawRecord.RawData[NextOfs]:=$ff;
  917. NextOfs:=RawRecord.WriteIndexedRef(NextOfs+1,Segment);
  918. end;
  919. RawRecord.RecordLength:=NextOfs+1;
  920. RawRecord.CalculateChecksumByte;
  921. end;
  922. { TOmfPublicNameElement }
  923. function TOmfPublicNameElement.GetLengthInFile(Is32Bit: Boolean): Integer;
  924. begin
  925. Result:=1+Length(Name)+2+1;
  926. if Is32Bit then
  927. Inc(Result,2);
  928. if TypeIndex>=$80 then
  929. Inc(Result);
  930. end;
  931. { TOmfRecord_PUBDEF }
  932. procedure TOmfRecord_PUBDEF.DecodeFrom(RawRecord: TOmfRawRecord);
  933. var
  934. NextOfs: Integer;
  935. Name: string;
  936. TypeIndex: Integer;
  937. PublicOffset: DWord;
  938. PubName: TOmfPublicNameElement;
  939. begin
  940. if not (RawRecord.RecordType in [RT_PUBDEF,RT_PUBDEF32]) then
  941. internalerror(2015040301);
  942. Is32Bit:=RawRecord.RecordType=RT_PUBDEF32;
  943. NextOfs:=RawRecord.ReadIndexedRef(0,FBaseGroupIndex);
  944. NextOfs:=RawRecord.ReadIndexedRef(NextOfs,FBaseSegmentIndex);
  945. if BaseSegmentIndex=0 then
  946. begin
  947. if (NextOfs+1)>=RawRecord.RecordLength then
  948. internalerror(2015041401);
  949. BaseFrame:=RawRecord.RawData[NextOfs]+(RawRecord.RawData[NextOfs+1] shl 8);
  950. Inc(NextOfs,2);
  951. end
  952. else
  953. BaseFrame:=0;
  954. while NextOfs<(RawRecord.RecordLength-1) do
  955. begin
  956. NextOfs:=RawRecord.ReadStringAt(NextOfs,Name);
  957. if Is32Bit then
  958. begin
  959. if (NextOfs+3)>=RawRecord.RecordLength then
  960. internalerror(2015041401);
  961. PublicOffset:=RawRecord.RawData[NextOfs]+(RawRecord.RawData[NextOfs+1] shl 8)+
  962. (RawRecord.RawData[NextOfs+2] shl 16)+(RawRecord.RawData[NextOfs+3] shl 24);
  963. Inc(NextOfs,4);
  964. end
  965. else
  966. begin
  967. if (NextOfs+1)>=RawRecord.RecordLength then
  968. internalerror(2015041401);
  969. PublicOffset:=RawRecord.RawData[NextOfs]+(RawRecord.RawData[NextOfs+1] shl 8);
  970. Inc(NextOfs,2);
  971. end;
  972. NextOfs:=RawRecord.ReadIndexedRef(NextOfs,TypeIndex);
  973. PubName:=TOmfPublicNameElement.Create(PublicNames,Name);
  974. PubName.PublicOffset:=PublicOffset;
  975. PubName.TypeIndex:=TypeIndex;
  976. end;
  977. end;
  978. procedure TOmfRecord_PUBDEF.EncodeTo(RawRecord: TOmfRawRecord);
  979. const
  980. RecordLengthLimit = 1024;
  981. var
  982. Len,LastIncludedIndex,NextOfs,I: Integer;
  983. PubName: TOmfPublicNameElement;
  984. begin
  985. if Is32Bit then
  986. RawRecord.RecordType:=RT_PUBDEF32
  987. else
  988. RawRecord.RecordType:=RT_PUBDEF;
  989. NextOfs:=RawRecord.WriteIndexedRef(0,BaseGroupIndex);
  990. NextOfs:=RawRecord.WriteIndexedRef(NextOfs,BaseSegmentIndex);
  991. if BaseSegmentIndex=0 then
  992. begin
  993. RawRecord.RawData[NextOfs]:=Byte(BaseFrame);
  994. RawRecord.RawData[NextOfs+1]:=Byte(BaseFrame shr 8);
  995. Inc(NextOfs,2);
  996. end;
  997. { find out how many public names can we include until we reach the length limit }
  998. Len:=NextOfs;
  999. LastIncludedIndex:=NextIndex-1;
  1000. repeat
  1001. Inc(LastIncludedIndex);
  1002. Inc(Len,TOmfPublicNameElement(PublicNames[LastIncludedIndex]).GetLengthInFile(Is32Bit));
  1003. until (LastIncludedIndex>=(PublicNames.Count-1)) or ((Len+TOmfPublicNameElement(PublicNames[LastIncludedIndex+1]).GetLengthInFile(Is32Bit))>=RecordLengthLimit);
  1004. { write the public names... }
  1005. for I:=NextIndex to LastIncludedIndex do
  1006. begin
  1007. PubName:=TOmfPublicNameElement(PublicNames[I]);
  1008. NextOfs:=RawRecord.WriteStringAt(NextOfs,PubName.Name);
  1009. if Is32Bit then
  1010. begin
  1011. RawRecord.RawData[NextOfs]:=Byte(PubName.PublicOffset);
  1012. RawRecord.RawData[NextOfs+1]:=Byte(PubName.PublicOffset shr 8);
  1013. RawRecord.RawData[NextOfs+2]:=Byte(PubName.PublicOffset shr 16);
  1014. RawRecord.RawData[NextOfs+3]:=Byte(PubName.PublicOffset shr 24);
  1015. Inc(NextOfs,4);
  1016. end
  1017. else
  1018. begin
  1019. if PubName.PublicOffset>$ffff then
  1020. internalerror(2015041403);
  1021. RawRecord.RawData[NextOfs]:=Byte(PubName.PublicOffset);
  1022. RawRecord.RawData[NextOfs+1]:=Byte(PubName.PublicOffset shr 8);
  1023. Inc(NextOfs,2);
  1024. end;
  1025. NextOfs:=RawRecord.WriteIndexedRef(NextOfs,PubName.TypeIndex);
  1026. end;
  1027. RawRecord.RecordLength:=Len+1;
  1028. RawRecord.CalculateChecksumByte;
  1029. { update NextIndex }
  1030. NextIndex:=LastIncludedIndex+1;
  1031. end;
  1032. { TOmfExternalNameElement }
  1033. function TOmfExternalNameElement.GetLengthInFile: Integer;
  1034. begin
  1035. Result:=1+Length(Name)+1;
  1036. if TypeIndex>=$80 then
  1037. Inc(Result);
  1038. end;
  1039. { TOmfRecord_EXTDEF }
  1040. procedure TOmfRecord_EXTDEF.DecodeFrom(RawRecord: TOmfRawRecord);
  1041. var
  1042. NextOfs: Integer;
  1043. Name: string;
  1044. TypeIndex: Integer;
  1045. ExtName: TOmfExternalNameElement;
  1046. begin
  1047. if RawRecord.RecordType<>RT_EXTDEF then
  1048. internalerror(2015040301);
  1049. NextOfs:=0;
  1050. while NextOfs<(RawRecord.RecordLength-1) do
  1051. begin
  1052. NextOfs:=RawRecord.ReadStringAt(NextOfs,Name);
  1053. NextOfs:=RawRecord.ReadIndexedRef(NextOfs,TypeIndex);
  1054. ExtName:=TOmfExternalNameElement.Create(ExternalNames,Name);
  1055. ExtName.TypeIndex:=TypeIndex;
  1056. end;
  1057. end;
  1058. procedure TOmfRecord_EXTDEF.EncodeTo(RawRecord: TOmfRawRecord);
  1059. const
  1060. RecordLengthLimit = 1024;
  1061. var
  1062. Len,LastIncludedIndex,NextOfs,I: Integer;
  1063. ExtName: TOmfExternalNameElement;
  1064. begin
  1065. RawRecord.RecordType:=RT_EXTDEF;
  1066. NextOfs:=0;
  1067. { find out how many external names can we include until we reach the length limit }
  1068. Len:=NextOfs;
  1069. LastIncludedIndex:=NextIndex-1;
  1070. repeat
  1071. Inc(LastIncludedIndex);
  1072. Inc(Len,TOmfExternalNameElement(ExternalNames[LastIncludedIndex]).GetLengthInFile);
  1073. until (LastIncludedIndex>=(ExternalNames.Count-1)) or ((Len+TOmfExternalNameElement(ExternalNames[LastIncludedIndex+1]).GetLengthInFile)>=RecordLengthLimit);
  1074. { write the external names... }
  1075. for I:=NextIndex to LastIncludedIndex do
  1076. begin
  1077. ExtName:=TOmfExternalNameElement(ExternalNames[I]);
  1078. NextOfs:=RawRecord.WriteStringAt(NextOfs,ExtName.Name);
  1079. NextOfs:=RawRecord.WriteIndexedRef(NextOfs,ExtName.TypeIndex);
  1080. end;
  1081. RawRecord.RecordLength:=Len+1;
  1082. RawRecord.CalculateChecksumByte;
  1083. { update NextIndex }
  1084. NextIndex:=LastIncludedIndex+1;
  1085. end;
  1086. { TOmfRecord_MODEND }
  1087. procedure TOmfRecord_MODEND.DecodeFrom(RawRecord: TOmfRawRecord);
  1088. var
  1089. ModTyp: Byte;
  1090. NextOfs: Integer;
  1091. EndData: Byte;
  1092. begin
  1093. if not (RawRecord.RecordType in [RT_MODEND,RT_MODEND32]) then
  1094. internalerror(2015040301);
  1095. Is32Bit:=RawRecord.RecordType=RT_MODEND32;
  1096. if RawRecord.RecordLength<2 then
  1097. internalerror(2015040305);
  1098. ModTyp:=RawRecord.RawData[0];
  1099. IsMainModule:=(ModTyp and $80)<>0;
  1100. HasStartAddress:=(ModTyp and $40)<>0;
  1101. SegmentBit:=(ModTyp and $20)<>0;
  1102. LogicalStartAddress:=(ModTyp and $01)<>0;
  1103. if (ModTyp and $1E)<>0 then
  1104. internalerror(2015041404);
  1105. NextOfs:=1;
  1106. { clear all the start address properties first }
  1107. FrameMethod:=Low(FrameMethod);
  1108. FrameDatum:=0;
  1109. TargetMethod:=Low(TargetMethod);
  1110. TargetDatum:=0;
  1111. TargetDisplacement:=0;
  1112. PhysFrameNumber:=0;
  1113. PhysOffset:=0;
  1114. if HasStartAddress then
  1115. begin
  1116. if LogicalStartAddress then
  1117. begin
  1118. if NextOfs>=RawRecord.RecordLength then
  1119. internalerror(2015040305);
  1120. EndData:=RawRecord.RawData[NextOfs];
  1121. Inc(NextOfs);
  1122. { frame and target method determined by thread is not allowed in MODEND records }
  1123. if (EndData and $88)<>0 then
  1124. internalerror(2015041406);
  1125. FrameMethod:=TOmfFixupFrameMethod((EndData shr 4) and 7);
  1126. TargetMethod:=TOmfFixupTargetMethod(EndData and 7);
  1127. { frame method ffmLocation is not allowed in an MODEND record }
  1128. if FrameMethod=ffmLocation then
  1129. internalerror(2015041402);
  1130. { read Frame Datum? }
  1131. if FrameMethod in [ffmSegmentIndex,ffmGroupIndex,ffmExternalIndex,ffmFrameNumber] then
  1132. NextOfs:=RawRecord.ReadIndexedRef(NextOfs,FFrameDatum);
  1133. { read Target Datum? }
  1134. NextOfs:=RawRecord.ReadIndexedRef(NextOfs,FTargetDatum);
  1135. { read Target Displacement? }
  1136. if TargetMethod in [ftmSegmentIndex,ftmGroupIndex,ftmExternalIndex,ftmFrameNumber] then
  1137. begin
  1138. if Is32Bit then
  1139. begin
  1140. if (NextOfs+3)>=RawRecord.RecordLength then
  1141. internalerror(2015040504);
  1142. TargetDisplacement := RawRecord.RawData[NextOfs]+
  1143. (RawRecord.RawData[NextOfs+1] shl 8)+
  1144. (RawRecord.RawData[NextOfs+2] shl 16)+
  1145. (RawRecord.RawData[NextOfs+3] shl 24);
  1146. Inc(NextOfs,4);
  1147. end
  1148. else
  1149. begin
  1150. if (NextOfs+1)>=RawRecord.RecordLength then
  1151. internalerror(2015040504);
  1152. TargetDisplacement := RawRecord.RawData[NextOfs]+
  1153. (RawRecord.RawData[NextOfs+1] shl 8);
  1154. Inc(NextOfs,2);
  1155. end;
  1156. end;
  1157. end
  1158. else
  1159. begin
  1160. { physical start address }
  1161. if (NextOfs+1)>=RawRecord.RecordLength then
  1162. internalerror(2015040305);
  1163. PhysFrameNumber:=RawRecord.RawData[NextOfs]+(RawRecord.RawData[NextOfs+1] shl 8);
  1164. Inc(NextOfs,2);
  1165. if Is32Bit then
  1166. begin
  1167. if (NextOfs+3)>=RawRecord.RecordLength then
  1168. internalerror(2015040305);
  1169. PhysOffset:=RawRecord.RawData[NextOfs]+(RawRecord.RawData[NextOfs+1] shl 8)+
  1170. (RawRecord.RawData[NextOfs+2] shl 16)+(RawRecord.RawData[NextOfs+3] shl 24);
  1171. Inc(NextOfs,4);
  1172. end
  1173. else
  1174. begin
  1175. if (NextOfs+1)>=RawRecord.RecordLength then
  1176. internalerror(2015040305);
  1177. PhysOffset:=RawRecord.RawData[NextOfs]+(RawRecord.RawData[NextOfs+1] shl 8);
  1178. Inc(NextOfs,2);
  1179. end;
  1180. end;
  1181. end;
  1182. end;
  1183. procedure TOmfRecord_MODEND.EncodeTo(RawRecord: TOmfRawRecord);
  1184. var
  1185. ModTyp: Byte;
  1186. NextOfs: Integer;
  1187. EndData: Byte;
  1188. begin
  1189. if Is32Bit then
  1190. RawRecord.RecordType:=RT_MODEND32
  1191. else
  1192. RawRecord.RecordType:=RT_MODEND;
  1193. ModTyp:=(Ord(IsMainModule) shl 7)+(Ord(HasStartAddress) shl 6)+(Ord(SegmentBit) shl 5)+Ord(LogicalStartAddress);
  1194. RawRecord.RawData[0]:=ModTyp;
  1195. NextOfs:=1;
  1196. if HasStartAddress then
  1197. begin
  1198. if LogicalStartAddress then
  1199. begin
  1200. { frame method ffmLocation is not allowed in an MODEND record }
  1201. if FrameMethod=ffmLocation then
  1202. internalerror(2015041402);
  1203. EndData:=(Ord(FrameMethod) shl 4)+Ord(TargetMethod);
  1204. RawRecord.RawData[NextOfs]:=EndData;
  1205. Inc(NextOfs);
  1206. { save Frame Datum? }
  1207. if FrameMethod in [ffmSegmentIndex,ffmGroupIndex,ffmExternalIndex,ffmFrameNumber] then
  1208. NextOfs:=RawRecord.WriteIndexedRef(NextOfs,FrameDatum);
  1209. { save Target Datum? }
  1210. NextOfs:=RawRecord.WriteIndexedRef(NextOfs,TargetDatum);
  1211. { save Target Displacement? }
  1212. if TargetMethod in [ftmSegmentIndex,ftmGroupIndex,ftmExternalIndex,ftmFrameNumber] then
  1213. begin
  1214. if Is32Bit then
  1215. begin
  1216. RawRecord.RawData[NextOfs]:=Byte(TargetDisplacement);
  1217. RawRecord.RawData[NextOfs+1]:=Byte(TargetDisplacement shr 8);
  1218. RawRecord.RawData[NextOfs+2]:=Byte(TargetDisplacement shr 16);
  1219. RawRecord.RawData[NextOfs+3]:=Byte(TargetDisplacement shr 24);
  1220. Inc(NextOfs,4);
  1221. end
  1222. else
  1223. begin
  1224. if TargetDisplacement>$ffff then
  1225. internalerror(2015040502);
  1226. RawRecord.RawData[NextOfs]:=Byte(TargetDisplacement);
  1227. RawRecord.RawData[NextOfs+1]:=Byte(TargetDisplacement shr 8);
  1228. Inc(NextOfs,2);
  1229. end;
  1230. end;
  1231. end
  1232. else
  1233. begin
  1234. { physical start address }
  1235. RawRecord.RawData[NextOfs]:=Byte(PhysFrameNumber);
  1236. RawRecord.RawData[NextOfs+1]:=Byte(PhysFrameNumber shr 8);
  1237. Inc(NextOfs,2);
  1238. if Is32Bit then
  1239. begin
  1240. RawRecord.RawData[NextOfs]:=Byte(PhysOffset);
  1241. RawRecord.RawData[NextOfs+1]:=Byte(PhysOffset shr 8);
  1242. RawRecord.RawData[NextOfs+2]:=Byte(PhysOffset shr 16);
  1243. RawRecord.RawData[NextOfs+3]:=Byte(PhysOffset shr 24);
  1244. Inc(NextOfs,4);
  1245. end
  1246. else
  1247. begin
  1248. if PhysOffset>$ffff then
  1249. internalerror(2015040502);
  1250. RawRecord.RawData[NextOfs]:=Byte(PhysOffset);
  1251. RawRecord.RawData[NextOfs+1]:=Byte(PhysOffset shr 8);
  1252. Inc(NextOfs,2);
  1253. end;
  1254. end;
  1255. end;
  1256. RawRecord.RecordLength:=NextOfs+1;
  1257. RawRecord.CalculateChecksumByte;
  1258. end;
  1259. { TOmfSubRecord_FIXUP }
  1260. function TOmfSubRecord_FIXUP.GetDataRecordOffset: Integer;
  1261. begin
  1262. Result:=FLocationOffset-FDataRecordStartOffset;
  1263. end;
  1264. function TOmfSubRecord_FIXUP.GetLocationSize: Integer;
  1265. const
  1266. OmfLocationType2Size: array [TOmfFixupLocationType] of Integer=
  1267. (1, // fltLoByte
  1268. 2, // fltOffset
  1269. 2, // fltBase
  1270. 4, // fltFarPointer
  1271. 1, // fltHiByte
  1272. 2, // fltLoaderResolvedOffset (PharLap: Offset32)
  1273. 0, // fltUndefined6 (PharLap: Pointer48)
  1274. 0, // fltUndefined7
  1275. 0, // fltUndefined8
  1276. 4, // fltOffset32
  1277. 0, // fltUndefined10
  1278. 6, // fltFarPointer48
  1279. 0, // fltUndefined12
  1280. 4, // fltLoaderResolvedOffset32
  1281. 0, // fltUndefined14
  1282. 0); // fltUndefined15
  1283. begin
  1284. Result:=OmfLocationType2Size[LocationType];
  1285. end;
  1286. procedure TOmfSubRecord_FIXUP.SetDataRecordOffset(AValue: Integer);
  1287. begin
  1288. FLocationOffset:=AValue+FDataRecordStartOffset;
  1289. end;
  1290. function TOmfSubRecord_FIXUP.ReadAt(RawRecord: TOmfRawRecord; Offset: Integer): Integer;
  1291. var
  1292. Locat: Word;
  1293. FixData: Byte;
  1294. begin
  1295. if (Offset+2)>=RawRecord.RecordLength then
  1296. internalerror(2015040504);
  1297. { unlike other fields in the OMF format, this one is big endian }
  1298. Locat:=(RawRecord.RawData[Offset] shl 8) or RawRecord.RawData[Offset+1];
  1299. FixData:=RawRecord.RawData[Offset+2];
  1300. Inc(Offset,3);
  1301. if (Locat and $8000)=0 then
  1302. internalerror(2015040503);
  1303. DataRecordOffset:=Locat and $3FF;
  1304. LocationType:=TOmfFixupLocationType((Locat shr 10) and 15);
  1305. Mode:=TOmfFixupMode((Locat shr 14) and 1);
  1306. FrameDeterminedByThread:=(FixData and $80)<>0;
  1307. TargetDeterminedByThread:=(FixData and $08)<>0;
  1308. if FrameDeterminedByThread then
  1309. FrameThread:=TOmfFixupThread((FixData shr 4) and 3)
  1310. else
  1311. FrameMethod:=TOmfFixupFrameMethod((FixData shr 4) and 7);
  1312. if TargetDeterminedByThread then
  1313. begin
  1314. TargetThread:=TOmfFixupThread(FixData and 3);
  1315. TargetThreadDisplacementPresent:=(FixData and $40)=0;
  1316. end
  1317. else
  1318. TargetMethod:=TOmfFixupTargetMethod(FixData and 7);
  1319. { read Frame Datum? }
  1320. if not FrameDeterminedByThread and (FrameMethod in [ffmSegmentIndex,ffmGroupIndex,ffmExternalIndex,ffmFrameNumber]) then
  1321. Offset:=RawRecord.ReadIndexedRef(Offset,FFrameDatum)
  1322. else
  1323. FrameDatum:=0;
  1324. { read Target Datum? }
  1325. if not TargetDeterminedByThread then
  1326. Offset:=RawRecord.ReadIndexedRef(Offset,FTargetDatum)
  1327. else
  1328. TargetDatum:=0;
  1329. { read Target Displacement? }
  1330. if (TargetDeterminedByThread and TargetThreadDisplacementPresent) or
  1331. (TargetMethod in [ftmSegmentIndex,ftmGroupIndex,ftmExternalIndex,ftmFrameNumber]) then
  1332. begin
  1333. if Is32Bit then
  1334. begin
  1335. if (Offset+3)>=RawRecord.RecordLength then
  1336. internalerror(2015040504);
  1337. TargetDisplacement := RawRecord.RawData[Offset]+
  1338. (RawRecord.RawData[Offset+1] shl 8)+
  1339. (RawRecord.RawData[Offset+2] shl 16)+
  1340. (RawRecord.RawData[Offset+3] shl 24);
  1341. Inc(Offset,4);
  1342. end
  1343. else
  1344. begin
  1345. if (Offset+1)>=RawRecord.RecordLength then
  1346. internalerror(2015040504);
  1347. TargetDisplacement := RawRecord.RawData[Offset]+
  1348. (RawRecord.RawData[Offset+1] shl 8);
  1349. Inc(Offset,2);
  1350. end;
  1351. end;
  1352. Result:=Offset;
  1353. end;
  1354. function TOmfSubRecord_FIXUP.WriteAt(RawRecord: TOmfRawRecord; Offset: Integer): Integer;
  1355. var
  1356. Locat: Word;
  1357. FixData: Byte;
  1358. begin
  1359. if (DataRecordOffset<0) or (DataRecordOffset>1023) then
  1360. internalerror(2015040501);
  1361. Locat:=$8000+(Ord(Mode) shl 14)+(Ord(LocationType) shl 10)+DataRecordOffset;
  1362. { unlike other fields in the OMF format, this one is big endian }
  1363. RawRecord.RawData[Offset]:=Byte(Locat shr 8);
  1364. RawRecord.RawData[Offset+1]:=Byte(Locat);
  1365. Inc(Offset, 2);
  1366. FixData:=(Ord(FrameDeterminedByThread) shl 7)+(Ord(TargetDeterminedByThread) shl 3);
  1367. if FrameDeterminedByThread then
  1368. FixData:=FixData+(Ord(FrameThread) shl 4)
  1369. else
  1370. FixData:=FixData+(Ord(FrameMethod) shl 4);
  1371. if TargetDeterminedByThread then
  1372. FixData:=FixData+Ord(TargetThread)+(Ord(not TargetThreadDisplacementPresent) shl 2)
  1373. else
  1374. FixData:=FixData+Ord(TargetMethod);
  1375. RawRecord.RawData[Offset]:=FixData;
  1376. Inc(Offset);
  1377. { save Frame Datum? }
  1378. if not FrameDeterminedByThread and (FrameMethod in [ffmSegmentIndex,ffmGroupIndex,ffmExternalIndex,ffmFrameNumber]) then
  1379. Offset:=RawRecord.WriteIndexedRef(Offset,FrameDatum);
  1380. { save Target Datum? }
  1381. if not TargetDeterminedByThread then
  1382. Offset:=RawRecord.WriteIndexedRef(Offset,TargetDatum);
  1383. { save Target Displacement? }
  1384. if (TargetDeterminedByThread and TargetThreadDisplacementPresent) or
  1385. (TargetMethod in [ftmSegmentIndex,ftmGroupIndex,ftmExternalIndex,ftmFrameNumber]) then
  1386. begin
  1387. if Is32Bit then
  1388. begin
  1389. RawRecord.RawData[Offset]:=Byte(TargetDisplacement);
  1390. RawRecord.RawData[Offset+1]:=Byte(TargetDisplacement shr 8);
  1391. RawRecord.RawData[Offset+2]:=Byte(TargetDisplacement shr 16);
  1392. RawRecord.RawData[Offset+3]:=Byte(TargetDisplacement shr 24);
  1393. Inc(Offset,4);
  1394. end
  1395. else
  1396. begin
  1397. if TargetDisplacement>$ffff then
  1398. internalerror(2015040502);
  1399. RawRecord.RawData[Offset]:=Byte(TargetDisplacement);
  1400. RawRecord.RawData[Offset+1]:=Byte(TargetDisplacement shr 8);
  1401. Inc(Offset,2);
  1402. end;
  1403. end;
  1404. Result:=Offset;
  1405. end;
  1406. { TOmfRecord_LIBHEAD }
  1407. constructor TOmfRecord_LIBHEAD.Create;
  1408. begin
  1409. PageSize:=512;
  1410. DictionarySizeInBlocks:=2;
  1411. CaseSensitive:=true;
  1412. end;
  1413. procedure TOmfRecord_LIBHEAD.SetPageSize(AValue: Integer);
  1414. var
  1415. p: longint;
  1416. begin
  1417. { valid library page sizes are powers of two, between 2**4 and 2**15 }
  1418. if not ispowerof2(AValue,p) then
  1419. internalerror(2015041802);
  1420. if (p<4) or (p>15) then
  1421. internalerror(2015041802);
  1422. FPageSize:=AValue;
  1423. end;
  1424. procedure TOmfRecord_LIBHEAD.DecodeFrom(RawRecord: TOmfRawRecord);
  1425. begin
  1426. if RawRecord.RecordType<>RT_LIBHEAD then
  1427. internalerror(2015040301);
  1428. { this will also range check PageSize and will ensure that RecordLength>=13 }
  1429. PageSize:=RawRecord.RecordLength+3;
  1430. DictionaryOffset:=RawRecord.RawData[0]+
  1431. (RawRecord.RawData[1] shl 8)+
  1432. (RawRecord.RawData[2] shl 16)+
  1433. (RawRecord.RawData[3] shl 24);
  1434. DictionarySizeInBlocks:=RawRecord.RawData[4]+
  1435. (RawRecord.RawData[5] shl 8);
  1436. Flags:=RawRecord.RawData[6];
  1437. end;
  1438. procedure TOmfRecord_LIBHEAD.EncodeTo(RawRecord: TOmfRawRecord);
  1439. begin
  1440. { make sure the LIBHEAD record is padded with zeros at the end }
  1441. FillChar(RawRecord.RawData,SizeOf(RawRecord.RawData),0);
  1442. RawRecord.RecordType:=RT_LIBHEAD;
  1443. RawRecord.RecordLength:=PageSize-3;
  1444. RawRecord.RawData[0]:=Byte(DictionaryOffset);
  1445. RawRecord.RawData[1]:=Byte(DictionaryOffset shr 8);
  1446. RawRecord.RawData[2]:=Byte(DictionaryOffset shr 16);
  1447. RawRecord.RawData[3]:=Byte(DictionaryOffset shr 24);
  1448. RawRecord.RawData[4]:=Byte(DictionarySizeInBlocks);
  1449. RawRecord.RawData[5]:=Byte(DictionarySizeInBlocks shr 8);
  1450. RawRecord.RawData[6]:=Flags;
  1451. { the LIBHEAD record contains no checksum byte, so no need to call
  1452. RawRecord.CalculateChecksumByte }
  1453. end;
  1454. function TOmfRecord_LIBHEAD.IsCaseSensitive: Boolean;
  1455. begin
  1456. Result:=(FFlags and 1)<>0;
  1457. end;
  1458. procedure TOmfRecord_LIBHEAD.SetCaseSensitive(AValue: Boolean);
  1459. begin
  1460. FFlags:=(FFlags and $FE) or Ord(AValue);
  1461. end;
  1462. { TOmfRecord_LIBEND }
  1463. procedure TOmfRecord_LIBEND.DecodeFrom(RawRecord: TOmfRawRecord);
  1464. begin
  1465. if RawRecord.RecordType<>RT_LIBEND then
  1466. internalerror(2015040301);
  1467. FPaddingBytes:=RawRecord.RecordLength;
  1468. end;
  1469. procedure TOmfRecord_LIBEND.EncodeTo(RawRecord: TOmfRawRecord);
  1470. begin
  1471. { make sure the LIBEND record is padded with zeros at the end }
  1472. FillChar(RawRecord.RawData,SizeOf(RawRecord.RawData),0);
  1473. RawRecord.RecordType:=RT_LIBEND;
  1474. RawRecord.RecordLength:=FPaddingBytes;
  1475. { the LIBEND record contains no checksum byte, so no need to call
  1476. RawRecord.CalculateChecksumByte }
  1477. end;
  1478. procedure TOmfRecord_LIBEND.CalculatePaddingBytes(RecordStartOffset: DWord);
  1479. var
  1480. DictionaryStartOffset: Integer;
  1481. begin
  1482. { padding must be calculated, so that the dictionary begins on a 512-byte boundary }
  1483. Inc(RecordStartOffset,3); // padding begins _after_ the record header (3 bytes)
  1484. DictionaryStartOffset:=(RecordStartOffset+511) and $fffffe00;
  1485. PaddingBytes:=DictionaryStartOffset-RecordStartOffset;
  1486. end;
  1487. function compute_omf_lib_hash(const name: string; blocks: Integer): TOmfLibHash;
  1488. const
  1489. blank=$20; // ASCII blank
  1490. nbuckets=37;
  1491. var
  1492. block_x: Integer;
  1493. block_d: Integer;
  1494. bucket_x: Integer;
  1495. bucket_d: Integer;
  1496. len: Integer;
  1497. pbidx,peidx: Integer;
  1498. cback,cfront: Byte;
  1499. begin
  1500. len:=Length(name);
  1501. if len=0 then
  1502. internalerror(2015041801);
  1503. pbidx:=1;
  1504. peidx:=len+1;
  1505. { left to right scan }
  1506. block_x:=len or blank;
  1507. bucket_d:=block_x;
  1508. { right to left scan }
  1509. block_d:=0;
  1510. bucket_x:=0;
  1511. while true do
  1512. begin
  1513. { blank -> convert to LC }
  1514. Dec(peidx);
  1515. cback:=Byte(name[peidx]) or blank;
  1516. bucket_x:=RorWord(bucket_x,2) xor cback;
  1517. block_d:=RolWord(block_d,2) xor cback;
  1518. Dec(len);
  1519. if len=0 then
  1520. break;
  1521. cfront:=Byte(name[pbidx]) or blank;
  1522. Inc(pbidx);
  1523. block_x:=RolWord(block_x,2) xor cfront;
  1524. bucket_d:=RorWord(bucket_d,2) xor cfront;
  1525. end;
  1526. Result.block_x:=block_x mod blocks;
  1527. Result.block_d:=max(block_d mod blocks,1);
  1528. Result.bucket_x:=bucket_x mod nbuckets;
  1529. Result.bucket_d:=max(bucket_d mod nbuckets,1);
  1530. end;
  1531. function omf_segclass(atype: TAsmSectiontype): string;
  1532. const
  1533. segclass : array[TAsmSectiontype] of string[length('DWARF')] = ('',
  1534. {user} 'DATA',
  1535. {code} 'CODE',
  1536. {data} 'DATA',
  1537. {rodata} 'DATA',
  1538. {rodata_norel} 'DATA',
  1539. {bss} 'BSS',
  1540. {threadvar} 'DATA',
  1541. {pdata} 'DATA',
  1542. {stub} 'CODE',
  1543. {data_nonlazy} 'DATA',
  1544. {data_lazy} 'DATA',
  1545. {init_func} 'DATA',
  1546. {term_func} 'DATA',
  1547. {stab} 'DATA',
  1548. {stabstr} 'DATA',
  1549. {idata2} 'DATA',
  1550. {idata4} 'DATA',
  1551. {idata5} 'DATA',
  1552. {idata6} 'DATA',
  1553. {idata7} 'DATA',
  1554. {edata} 'DATA',
  1555. {eh_frame} 'DATA',
  1556. {debug_frame} 'DWARF',
  1557. {debug_info} 'DWARF',
  1558. {debug_line} 'DWARF',
  1559. {debug_abbrev} 'DWARF',
  1560. {fpc} 'DATA',
  1561. {toc} 'DATA',
  1562. {init} 'CODE',
  1563. {fini} 'CODE',
  1564. {objc_class} 'DATA',
  1565. {objc_meta_class} 'DATA',
  1566. {objc_cat_cls_meth} 'DATA',
  1567. {objc_cat_inst_meth} 'DATA',
  1568. {objc_protocol} 'DATA',
  1569. {objc_string_object} 'DATA',
  1570. {objc_cls_meth} 'DATA',
  1571. {objc_inst_meth} 'DATA',
  1572. {objc_cls_refs} 'DATA',
  1573. {objc_message_refs} 'DATA',
  1574. {objc_symbols} 'DATA',
  1575. {objc_category} 'DATA',
  1576. {objc_class_vars} 'DATA',
  1577. {objc_instance_vars} 'DATA',
  1578. {objc_module_info} 'DATA',
  1579. {objc_class_names} 'DATA',
  1580. {objc_meth_var_types} 'DATA',
  1581. {objc_meth_var_names} 'DATA',
  1582. {objc_selector_strs} 'DATA',
  1583. {objc_protocol_ext} 'DATA',
  1584. {objc_class_ext} 'DATA',
  1585. {objc_property} 'DATA',
  1586. {objc_image_info} 'DATA',
  1587. {objc_cstring_object} 'DATA',
  1588. {objc_sel_fixup} 'DATA',
  1589. {objc_data} 'DATA',
  1590. {objc_const} 'DATA',
  1591. {objc_sup_refs} 'DATA',
  1592. {data_coalesced} 'DATA',
  1593. {objc_classlist} 'DATA',
  1594. {objc_nlclasslist} 'DATA',
  1595. {objc_catlist} 'DATA',
  1596. {objc_nlcatlist} 'DATA',
  1597. {objc_protolist} 'DATA',
  1598. {stack} 'STACK',
  1599. {heap} 'HEAP'
  1600. );
  1601. begin
  1602. result:=segclass[atype];
  1603. {$ifdef i8086}
  1604. if (current_settings.x86memorymodel=mm_huge) and
  1605. ((result='DATA') or (result='BSS')) then
  1606. result:='FAR_DATA';
  1607. {$endif i8086}
  1608. end;
  1609. function omf_sectiontype2align(atype: TAsmSectiontype): shortint;
  1610. begin
  1611. case atype of
  1612. sec_stabstr:
  1613. result:=1;
  1614. sec_code:
  1615. result:=1;
  1616. sec_data,
  1617. sec_rodata,
  1618. sec_rodata_norel,
  1619. sec_bss:
  1620. result:=2;
  1621. { For idata (at least idata2) it must be 4 bytes, because
  1622. an entry is always (also in win64) 20 bytes and aligning
  1623. on 8 bytes will insert 4 bytes between the entries resulting
  1624. in a corrupt idata section.
  1625. Same story with .pdata, it has 4-byte elements which should
  1626. be packed without gaps. }
  1627. sec_idata2,sec_idata4,sec_idata5,sec_idata6,sec_idata7,sec_pdata:
  1628. result:=4;
  1629. sec_debug_frame,sec_debug_info,sec_debug_line,sec_debug_abbrev:
  1630. result:=4;
  1631. sec_stack,
  1632. sec_heap:
  1633. result:=16;
  1634. else
  1635. result:=1;
  1636. end;
  1637. end;
  1638. function section_belongs_to_dgroup(atype: TAsmSectiontype): Boolean;
  1639. begin
  1640. {$ifdef i8086}
  1641. case omf_segclass(atype) of
  1642. 'CODE':
  1643. result:=current_settings.x86memorymodel=mm_tiny;
  1644. 'FAR_DATA':
  1645. result:=false;
  1646. 'DATA',
  1647. 'BSS':
  1648. result:=true;
  1649. 'STACK':
  1650. result:=current_settings.x86memorymodel in (x86_near_data_models-[mm_tiny]);
  1651. 'HEAP':
  1652. result:=current_settings.x86memorymodel in x86_near_data_models;
  1653. else
  1654. result:=false;
  1655. end;
  1656. {$else i8086}
  1657. result:=false;
  1658. {$endif i8086}
  1659. end;
  1660. end.