ogcoff.pas 107 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988
  1. {
  2. Copyright (c) 1998-2006 by Peter Vreman
  3. Contains the binary coff/PE reader and writer
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  15. ****************************************************************************
  16. }
  17. unit ogcoff;
  18. {$i fpcdefs.inc}
  19. interface
  20. uses
  21. { common }
  22. cclasses,globtype,
  23. { target }
  24. systems,
  25. { assembler }
  26. cpuinfo,cpubase,aasmbase,assemble,link,
  27. { output }
  28. ogbase,
  29. owbase;
  30. const
  31. PE_DATADIR_ENTRIES = 16;
  32. type
  33. tcoffpedatadir = packed record
  34. vaddr : longword;
  35. size : longword;
  36. end;
  37. tcoffheader = packed record
  38. mach : word;
  39. nsects : word;
  40. time : longword;
  41. sympos : longword;
  42. syms : longword;
  43. opthdr : word;
  44. flag : word;
  45. end;
  46. tcoffpeoptheader = packed record
  47. Magic : word;
  48. MajorLinkerVersion : byte;
  49. MinorLinkerVersion : byte;
  50. tsize : longword;
  51. dsize : longword;
  52. bsize : longword;
  53. entry : longword;
  54. text_start : longword;
  55. {$ifndef x86_64}
  56. data_start : longword;
  57. {$endif x86_64}
  58. ImageBase : aword;
  59. SectionAlignment : longword;
  60. FileAlignment : longword;
  61. MajorOperatingSystemVersion : word;
  62. MinorOperatingSystemVersion : word;
  63. MajorImageVersion : word;
  64. MinorImageVersion : word;
  65. MajorSubsystemVersion : word;
  66. MinorSubsystemVersion : word;
  67. Win32Version : longword;
  68. SizeOfImage : longword;
  69. SizeOfHeaders : longword;
  70. CheckSum : longword;
  71. Subsystem : word;
  72. DllCharacteristics : word;
  73. SizeOfStackReserve : aword;
  74. SizeOfStackCommit : aword;
  75. SizeOfHeapReserve : aword;
  76. SizeOfHeapCommit : aword;
  77. LoaderFlags : longword; { This field is obsolete }
  78. NumberOfRvaAndSizes : longword;
  79. DataDirectory : array[0..PE_DATADIR_ENTRIES-1] of tcoffpedatadir;
  80. end;
  81. tcoffsechdr = packed record
  82. name : array[0..7] of char;
  83. vsize : longword;
  84. rvaofs : longword;
  85. datasize : longword;
  86. datapos : longword;
  87. relocpos : longword;
  88. lineno1 : longword;
  89. nrelocs : word;
  90. lineno2 : word;
  91. flags : longword;
  92. end;
  93. TCoffObjSection = class(TObjSection)
  94. private
  95. orgmempos,
  96. coffrelocs,
  97. coffrelocpos : aword;
  98. public
  99. secidx : longword;
  100. flags : longword;
  101. constructor create(AList:TFPHashObjectList;const Aname:string;Aalign:shortint;Aoptions:TObjSectionOptions);override;
  102. procedure addsymsizereloc(ofs:aword;p:TObjSymbol;symsize:aword;reloctype:TObjRelocationType);
  103. procedure fixuprelocs;override;
  104. end;
  105. TDJCoffObjSection = class(TCoffObjSection)
  106. constructor create(AList:TFPHashObjectList;const Aname:string;Aalign:shortint;Aoptions:TObjSectionOptions);override;
  107. end;
  108. TPECoffObjSection = class(TCoffObjSection)
  109. constructor create(AList:TFPHashObjectList;const Aname:string;Aalign:shortint;Aoptions:TObjSectionOptions);override;
  110. end;
  111. TCoffObjData = class(TObjData)
  112. private
  113. win32 : boolean;
  114. {$ifdef arm}
  115. eVCobj : boolean;
  116. {$endif arm}
  117. public
  118. constructor createcoff(const n:string;awin32:boolean;acObjSection:TObjSectionClass);
  119. destructor destroy;override;
  120. procedure CreateDebugSections;override;
  121. function sectionname(atype:TAsmSectiontype;const aname:string;aorder:TAsmSectionOrder):string;override;
  122. procedure writereloc(data:aint;len:aword;p:TObjSymbol;reloctype:TObjRelocationType);override;
  123. procedure afteralloc;override;
  124. end;
  125. TDJCoffObjData = class(TCoffObjData)
  126. constructor create(const n:string);override;
  127. end;
  128. TPECoffObjData = class(TCoffObjData)
  129. constructor create(const n:string);override;
  130. end;
  131. TCoffObjOutput = class(tObjOutput)
  132. private
  133. win32 : boolean;
  134. symidx : longint;
  135. FCoffSyms,
  136. FCoffStrs : tdynamicarray;
  137. procedure write_symbol(const name:string;value:aword;section:smallint;typ,aux:byte);
  138. procedure section_write_symbol(p:TObject;arg:pointer);
  139. procedure section_write_relocs(p:TObject;arg:pointer);
  140. procedure create_symbols(data:TObjData);
  141. procedure section_set_datapos(p:TObject;arg:pointer);
  142. procedure section_set_reloc_datapos(p:TObject;arg:pointer);
  143. procedure section_write_header(p:TObject;arg:pointer);
  144. procedure section_write_data(p:TObject;arg:pointer);
  145. protected
  146. function writedata(data:TObjData):boolean;override;
  147. public
  148. constructor createcoff(AWriter:TObjectWriter;awin32:boolean);
  149. destructor destroy;override;
  150. end;
  151. TDJCoffObjOutput = class(TCoffObjOutput)
  152. constructor create(AWriter:TObjectWriter);override;
  153. end;
  154. TPECoffObjOutput = class(TCoffObjOutput)
  155. constructor create(AWriter:TObjectWriter);override;
  156. end;
  157. TCoffObjInput = class(tObjInput)
  158. private
  159. FCoffsyms,
  160. FCoffStrs : tdynamicarray;
  161. { Convert symidx -> TObjSymbol }
  162. FSymTbl : ^TObjSymbolArray;
  163. { Convert secidx -> TObjSection }
  164. FSecCount : smallint;
  165. FSecTbl : ^TObjSectionArray;
  166. win32 : boolean;
  167. function GetSection(secidx:longint):TObjSection;
  168. function Read_str(strpos:longword):string;
  169. procedure read_relocs(s:TCoffObjSection);
  170. procedure read_symbols(objdata:TObjData);
  171. procedure ObjSections_read_data(p:TObject;arg:pointer);
  172. procedure ObjSections_read_relocs(p:TObject;arg:pointer);
  173. public
  174. constructor createcoff(awin32:boolean);
  175. destructor destroy;override;
  176. function ReadObjData(AReader:TObjectreader;objdata:TObjData):boolean;override;
  177. end;
  178. TDJCoffObjInput = class(TCoffObjInput)
  179. constructor create;override;
  180. end;
  181. TPECoffObjInput = class(TCoffObjInput)
  182. constructor create;override;
  183. end;
  184. TCoffExeSection = class(TExeSection)
  185. private
  186. win32 : boolean;
  187. public
  188. constructor createcoff(AList:TFPHashObjectList;const n:string;awin32:boolean);
  189. end;
  190. TDJCoffExeSection = class(TCoffExeSection)
  191. constructor create(AList:TFPHashObjectList;const n:string);override;
  192. end;
  193. TPECoffExeSection = class(TCoffExeSection)
  194. constructor create(AList:TFPHashObjectList;const n:string);override;
  195. end;
  196. TCoffexeoutput = class(texeoutput)
  197. private
  198. FCoffsyms,
  199. FCoffStrs : tdynamicarray;
  200. win32 : boolean;
  201. nsects : word;
  202. nsyms,
  203. sympos : aword;
  204. function totalheadersize:longword;
  205. procedure ExeSectionList_pass2_header(p:TObject;arg:pointer);
  206. procedure write_symbol(const name:string;value:aword;section:smallint;typ,aux:byte);
  207. procedure globalsyms_write_symbol(p:TObject;arg:pointer);
  208. procedure ExeSectionList_write_header(p:TObject;arg:pointer);
  209. procedure ExeSectionList_write_data(p:TObject;arg:pointer);
  210. protected
  211. function writedata:boolean;override;
  212. procedure Order_ObjSectionList(ObjSectionList : TFPObjectList);override;
  213. public
  214. constructor createcoff(awin32:boolean);
  215. procedure MemPos_Header;override;
  216. procedure DataPos_Header;override;
  217. procedure DataPos_Symbols;override;
  218. end;
  219. TDJCoffexeoutput = class(TCoffexeoutput)
  220. constructor create;override;
  221. end;
  222. TPECoffexeoutput = class(TCoffexeoutput)
  223. private
  224. idatalabnr : longword;
  225. procedure GenerateRelocs;
  226. public
  227. constructor create;override;
  228. procedure GenerateLibraryImports(ImportLibraryList:TFPHashObjectList);override;
  229. procedure Order_End;override;
  230. procedure MemPos_ExeSection(const aname:string);override;
  231. end;
  232. TObjSymbolrec = record
  233. sym : TObjSymbol;
  234. orgsize : aword;
  235. end;
  236. TObjSymbolArray = array[0..high(word)] of TObjSymbolrec;
  237. TObjSectionArray = array[0..high(smallint)] of TObjSection;
  238. TDJCoffAssembler = class(tinternalassembler)
  239. constructor create(smart:boolean);override;
  240. end;
  241. TPECoffassembler = class(tinternalassembler)
  242. constructor create(smart:boolean);override;
  243. end;
  244. type
  245. Treaddllproc = procedure(const dllname,funcname:string) of object;
  246. const
  247. {$ifdef i386}
  248. COFF_MAGIC = $14c;
  249. COFF_OPT_MAGIC = $10b;
  250. {$endif i386}
  251. {$ifdef arm}
  252. COFF_MAGIC = $1c0;
  253. COFF_OPT_MAGIC = $10b;
  254. {$endif arm}
  255. {$ifdef x86_64}
  256. COFF_MAGIC = $8664;
  257. COFF_OPT_MAGIC = $20b;
  258. {$endif x86_64}
  259. function ReadDLLImports(const dllname:string;readdllproc:Treaddllproc):boolean;
  260. implementation
  261. uses
  262. {$ifdef win32}
  263. Windows,
  264. {$endif win32}
  265. SysUtils,
  266. cutils,verbose,globals,
  267. fmodule,aasmtai,aasmdata,
  268. ogmap,
  269. version
  270. ;
  271. const
  272. COFF_FLAG_NORELOCS = $0001;
  273. COFF_FLAG_EXE = $0002;
  274. COFF_FLAG_NOLINES = $0004;
  275. COFF_FLAG_NOLSYMS = $0008;
  276. COFF_FLAG_AR16WR = $0080; { 16bit little endian }
  277. COFF_FLAG_AR32WR = $0100; { 32bit little endian }
  278. COFF_FLAG_AR32W = $0200; { 32bit big endian }
  279. COFF_FLAG_DLL = $2000;
  280. COFF_SYM_GLOBAL = 2;
  281. COFF_SYM_LOCAL = 3;
  282. COFF_SYM_LABEL = 6;
  283. COFF_SYM_FUNCTION = 101;
  284. COFF_SYM_FILE = 103;
  285. COFF_SYM_SECTION = 104;
  286. COFF_STYP_REG = $0000; { "regular": allocated, relocated, loaded }
  287. COFF_STYP_DSECT = $0001; { "dummy": relocated only }
  288. COFF_STYP_NOLOAD = $0002; { "noload": allocated, relocated, not loaded }
  289. COFF_STYP_GROUP = $0004; { "grouped": formed of input sections }
  290. COFF_STYP_PAD = $0008;
  291. COFF_STYP_COPY = $0010;
  292. COFF_STYP_TEXT = $0020;
  293. COFF_STYP_DATA = $0040;
  294. COFF_STYP_BSS = $0080;
  295. PE_SUBSYSTEM_WINDOWS_GUI = 2;
  296. PE_SUBSYSTEM_WINDOWS_CUI = 3;
  297. PE_SUBSYSTEM_WINDOWS_CE_GUI = 9;
  298. PE_FILE_RELOCS_STRIPPED = $0001;
  299. PE_FILE_EXECUTABLE_IMAGE = $0002;
  300. PE_FILE_LINE_NUMS_STRIPPED = $0004;
  301. PE_FILE_LOCAL_SYMS_STRIPPED = $0008;
  302. PE_FILE_AGGRESSIVE_WS_TRIM = $0010;
  303. PE_FILE_LARGE_ADDRESS_AWARE = $0020;
  304. PE_FILE_16BIT_MACHINE = $0040;
  305. PE_FILE_BYTES_REVERSED_LO = $0080;
  306. PE_FILE_32BIT_MACHINE = $0100;
  307. PE_FILE_DEBUG_STRIPPED = $0200;
  308. PE_FILE_REMOVABLE_RUN_FROM_SWAP = $0400;
  309. PE_FILE_NET_RUN_FROM_SWAP = $0800;
  310. PE_FILE_SYSTEM = $1000;
  311. PE_FILE_DLL = $2000;
  312. PE_FILE_UP_SYSTEM_ONLY = $4000;
  313. PE_FILE_BYTES_REVERSED_HI = $8000;
  314. PE_SCN_CNT_CODE = $00000020; { Section contains code. }
  315. PE_SCN_CNT_INITIALIZED_DATA = $00000040; { Section contains initialized data. }
  316. PE_SCN_CNT_UNINITIALIZED_DATA = $00000080; { Section contains uninitialized data. }
  317. PE_SCN_LNK_OTHER = $00000100; { Reserved. }
  318. PE_SCN_LNK_INFO = $00000200; { Section contains comments or some other type of information. }
  319. PE_SCN_LNK_REMOVE = $00000800; { Section contents will not become part of image. }
  320. PE_SCN_LNK_COMDAT = $00001000; { Section contents comdat. }
  321. PE_SCN_MEM_FARDATA = $00008000;
  322. PE_SCN_MEM_PURGEABLE = $00020000;
  323. PE_SCN_MEM_16BIT = $00020000;
  324. PE_SCN_MEM_LOCKED = $00040000;
  325. PE_SCN_MEM_PRELOAD = $00080000;
  326. PE_SCN_ALIGN_MASK = $00f00000;
  327. PE_SCN_ALIGN_1BYTES = $00100000;
  328. PE_SCN_ALIGN_2BYTES = $00200000;
  329. PE_SCN_ALIGN_4BYTES = $00300000;
  330. PE_SCN_ALIGN_8BYTES = $00400000;
  331. PE_SCN_ALIGN_16BYTES = $00500000; { Default alignment if no others are specified. }
  332. PE_SCN_ALIGN_32BYTES = $00600000;
  333. PE_SCN_ALIGN_64BYTES = $00700000;
  334. PE_SCN_LNK_NRELOC_OVFL = $01000000; { Section contains extended relocations. }
  335. PE_SCN_MEM_NOT_CACHED = $04000000; { Section is not cachable. }
  336. PE_SCN_MEM_NOT_PAGED = $08000000; { Section is not pageable. }
  337. PE_SCN_MEM_SHARED = $10000000; { Section is shareable. }
  338. PE_SCN_MEM_DISCARDABLE = $02000000;
  339. PE_SCN_MEM_EXECUTE = $20000000;
  340. PE_SCN_MEM_READ = $40000000;
  341. PE_SCN_MEM_WRITE = $80000000;
  342. PE_DATADIR_EDATA = 0;
  343. PE_DATADIR_IDATA = 1;
  344. PE_DATADIR_RSRC = 2;
  345. PE_DATADIR_PDATA = 3;
  346. PE_DATADIR_SECURITY = 4;
  347. PE_DATADIR_RELOC = 5;
  348. PE_DATADIR_DEBUG = 6;
  349. PE_DATADIR_DESCRIPTION = 7;
  350. PE_DATADIR_SPECIAL = 8;
  351. PE_DATADIR_TLS = 9;
  352. PE_DATADIR_LOADCFG = 10;
  353. PE_DATADIR_BOUNDIMPORT = 11;
  354. PE_DATADIR_IMPORTADDRESSTABLE = 12;
  355. PE_DATADIR_DELAYIMPORT = 13;
  356. {$ifdef x86_64}
  357. IMAGE_REL_AMD64_ABSOLUTE = $0000; { Reference is absolute, no relocation is necessary }
  358. IMAGE_REL_AMD64_ADDR64 = $0001; { 64-bit address (VA). }
  359. IMAGE_REL_AMD64_ADDR32 = $0002; { 32-bit address (VA). }
  360. IMAGE_REL_AMD64_ADDR32NB = $0003; { 32-bit address w/o image base (RVA). }
  361. IMAGE_REL_AMD64_REL32 = $0004; { 32-bit relative address from byte following reloc }
  362. IMAGE_REL_AMD64_REL32_1 = $0005; { 32-bit relative address from byte distance 1 from reloc }
  363. IMAGE_REL_AMD64_REL32_2 = $0006; { 32-bit relative address from byte distance 2 from reloc }
  364. IMAGE_REL_AMD64_REL32_3 = $0007; { 32-bit relative address from byte distance 3 from reloc }
  365. IMAGE_REL_AMD64_REL32_4 = $0008; { 32-bit relative address from byte distance 4 from reloc }
  366. IMAGE_REL_AMD64_REL32_5 = $0009; { 32-bit relative address from byte distance 5 from reloc }
  367. IMAGE_REL_AMD64_SECTION = $000A; { Section index }
  368. IMAGE_REL_AMD64_SECREL = $000B; { 32 bit offset from base of section containing target }
  369. IMAGE_REL_AMD64_SECREL7 = $000C; { 7 bit unsigned offset from base of section containing target }
  370. IMAGE_REL_AMD64_TOKEN = $000D; { 32 bit metadata token }
  371. IMAGE_REL_AMD64_SREL32 = $000E; { 32 bit signed span-dependent value emitted into object }
  372. IMAGE_REL_AMD64_PAIR = $000F;
  373. IMAGE_REL_AMD64_SSPAN32 = $0010; { 32 bit signed span-dependent value applied at link time }
  374. {$endif x86_64}
  375. {$ifdef arm}
  376. IMAGE_REL_ARM_ABSOLUTE = $0000; { No relocation required }
  377. IMAGE_REL_ARM_ADDR32 = $0001; { 32 bit address }
  378. IMAGE_REL_ARM_ADDR32NB = $0002; { 32 bit address w/o image base }
  379. IMAGE_REL_ARM_BRANCH24 = $0003; { 24 bit offset << 2 & sign ext. }
  380. IMAGE_REL_ARM_BRANCH11 = $0004; { Thumb: 2 11 bit offsets }
  381. IMAGE_REL_ARM_TOKEN = $0005; { clr token }
  382. IMAGE_REL_ARM_GPREL12 = $0006; { GP-relative addressing (ARM) }
  383. IMAGE_REL_ARM_GPREL7 = $0007; { GP-relative addressing (Thumb) }
  384. IMAGE_REL_ARM_BLX24 = $0008;
  385. IMAGE_REL_ARM_BLX11 = $0009;
  386. IMAGE_REL_ARM_SECTION = $000E; { Section table index }
  387. IMAGE_REL_ARM_SECREL = $000F; { Offset within section }
  388. {$endif arm}
  389. {$ifdef i386}
  390. IMAGE_REL_I386_DIR32 = 6;
  391. IMAGE_REL_I386_IMAGEBASE = 7;
  392. IMAGE_REL_I386_SECREL32 = 11;
  393. IMAGE_REL_I386_PCRLONG = 20;
  394. {$endif i386}
  395. { .reloc section fixup types }
  396. IMAGE_REL_BASED_HIGHLOW = 3; { Applies the delta to the 32-bit field at Offset. }
  397. IMAGE_REL_BASED_DIR64 = 10; { Applies the delta to the 64-bit field at Offset. }
  398. type
  399. coffdjoptheader=packed record
  400. magic : word;
  401. vstamp : word;
  402. tsize : longint;
  403. dsize : longint;
  404. bsize : longint;
  405. entry : longint;
  406. text_start : longint;
  407. data_start : longint;
  408. end;
  409. coffsectionrec=packed record
  410. len : longword;
  411. nrelocs : word;
  412. empty : array[0..11] of char;
  413. end;
  414. coffreloc=packed record
  415. address : longword;
  416. sym : longword;
  417. reloctype : word;
  418. end;
  419. coffsymbol=packed record
  420. name : array[0..3] of char; { real is [0..7], which overlaps the strpos ! }
  421. strpos : longword;
  422. value : longword;
  423. section : smallint;
  424. empty : word;
  425. typ : byte;
  426. aux : byte;
  427. end;
  428. const
  429. SymbolMaxGrow = 200*sizeof(coffsymbol);
  430. StrsMaxGrow = 8192;
  431. coffsecnames : array[TAsmSectiontype] of string[20] = ('',
  432. '.text','.data','.data','.data','.bss','.tls',
  433. '.text',
  434. '.pdata',
  435. '.stab','.stabstr',
  436. '.idata$2','.idata$4','.idata$5','.idata$6','.idata$7','.edata',
  437. '.eh_frame',
  438. '.debug_frame','.debug_info','.debug_line','.debug_abbrev',
  439. '.fpc',
  440. '',
  441. '.init',
  442. '.fini',
  443. '.objc_class',
  444. '.objc_meta_class',
  445. '.objc_cat_cls_meth',
  446. '.objc_cat_inst_meth',
  447. '.objc_protocol',
  448. '.objc_string_object',
  449. '.objc_cls_meth',
  450. '.objc_inst_meth',
  451. '.objc_cls_refs',
  452. '.objc_message_refs',
  453. '.objc_symbols',
  454. '.objc_category',
  455. '.objc_class_vars',
  456. '.objc_instance_vars',
  457. '.objc_module_info',
  458. '.objc_class_names',
  459. '.objc_meth_var_types',
  460. '.objc_meth_var_names',
  461. '.objc_selector_strs',
  462. '.objc_protocol_ext',
  463. '.objc_class_ext',
  464. '.objc_property',
  465. '.objc_image_info',
  466. '.objc_cstring_object',
  467. '.objc_sel_fixup'
  468. );
  469. const go32v2stub : array[0..2047] of byte=(
  470. $4D,$5A,$00,$00,$04,$00,$00,$00,$20,$00,$27,$00,$FF,$FF,$00,
  471. $00,$60,$07,$00,$00,$54,$00,$00,$00,$00,$00,$00,$00,$0D,$0A,
  472. $73,$74,$75,$62,$2E,$68,$20,$67,$65,$6E,$65,$72,$61,$74,$65,
  473. $64,$20,$66,$72,$6F,$6D,$20,$73,$74,$75,$62,$2E,$61,$73,$6D,
  474. $20,$62,$79,$20,$64,$6A,$61,$73,$6D,$2C,$20,$6F,$6E,$20,$54,
  475. $68,$75,$20,$44,$65,$63,$20,$20,$39,$20,$31,$30,$3A,$35,$39,
  476. $3A,$33,$31,$20,$31,$39,$39,$39,$0D,$0A,$54,$68,$65,$20,$53,
  477. $54,$55,$42,$2E,$45,$58,$45,$20,$73,$74,$75,$62,$20,$6C,$6F,
  478. $61,$64,$65,$72,$20,$69,$73,$20,$43,$6F,$70,$79,$72,$69,$67,
  479. $68,$74,$20,$28,$43,$29,$20,$31,$39,$39,$33,$2D,$31,$39,$39,
  480. $35,$20,$44,$4A,$20,$44,$65,$6C,$6F,$72,$69,$65,$2E,$20,$0D,
  481. $0A,$50,$65,$72,$6D,$69,$73,$73,$69,$6F,$6E,$20,$67,$72,$61,
  482. $6E,$74,$65,$64,$20,$74,$6F,$20,$75,$73,$65,$20,$66,$6F,$72,
  483. $20,$61,$6E,$79,$20,$70,$75,$72,$70,$6F,$73,$65,$20,$70,$72,
  484. $6F,$76,$69,$64,$65,$64,$20,$74,$68,$69,$73,$20,$63,$6F,$70,
  485. $79,$72,$69,$67,$68,$74,$20,$0D,$0A,$72,$65,$6D,$61,$69,$6E,
  486. $73,$20,$70,$72,$65,$73,$65,$6E,$74,$20,$61,$6E,$64,$20,$75,
  487. $6E,$6D,$6F,$64,$69,$66,$69,$65,$64,$2E,$20,$0D,$0A,$54,$68,
  488. $69,$73,$20,$6F,$6E,$6C,$79,$20,$61,$70,$70,$6C,$69,$65,$73,
  489. $20,$74,$6F,$20,$74,$68,$65,$20,$73,$74,$75,$62,$2C,$20,$61,
  490. $6E,$64,$20,$6E,$6F,$74,$20,$6E,$65,$63,$65,$73,$73,$61,$72,
  491. $69,$6C,$79,$20,$74,$68,$65,$20,$77,$68,$6F,$6C,$65,$20,$70,
  492. $72,$6F,$67,$72,$61,$6D,$2E,$0A,$0D,$0A,$24,$49,$64,$3A,$20,
  493. $73,$74,$75,$62,$2E,$61,$73,$6D,$20,$62,$75,$69,$6C,$74,$20,
  494. $31,$32,$2F,$30,$39,$2F,$39,$39,$20,$31,$30,$3A,$35,$39,$3A,
  495. $33,$31,$20,$62,$79,$20,$64,$6A,$61,$73,$6D,$20,$24,$0A,$0D,
  496. $0A,$40,$28,$23,$29,$20,$73,$74,$75,$62,$2E,$61,$73,$6D,$20,
  497. $62,$75,$69,$6C,$74,$20,$31,$32,$2F,$30,$39,$2F,$39,$39,$20,
  498. $31,$30,$3A,$35,$39,$3A,$33,$31,$20,$62,$79,$20,$64,$6A,$61,
  499. $73,$6D,$0A,$0D,$0A,$1A,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  500. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  501. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  502. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  503. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  504. $00,$00,$67,$6F,$33,$32,$73,$74,$75,$62,$2C,$20,$76,$20,$32,
  505. $2E,$30,$32,$54,$00,$00,$00,$00,$00,$08,$00,$00,$00,$00,$00,
  506. $00,$00,$00,$00,$00,$40,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  507. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  508. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$43,$57,$53,$44,$50,
  509. $4D,$49,$2E,$45,$58,$45,$00,$00,$00,$00,$00,$0E,$1F,$8C,$1E,
  510. $24,$00,$8C,$06,$60,$07,$FC,$B4,$30,$CD,$21,$3C,$03,$73,$08,
  511. $B0,$6D,$BA,$A7,$05,$E9,$D4,$03,$A2,$69,$08,$BE,$20,$00,$8B,
  512. $04,$09,$C0,$75,$02,$B4,$FE,$BB,$70,$08,$39,$C3,$73,$02,$89,
  513. $C3,$89,$1C,$FE,$C7,$B9,$04,$FF,$D3,$EB,$B4,$4A,$CD,$21,$73,
  514. $08,$D3,$E3,$FE,$CF,$89,$1C,$EB,$D8,$26,$8E,$06,$2C,$00,$31,
  515. $FF,$30,$C0,$A9,$F2,$AE,$26,$81,$3D,$50,$41,$75,$15,$AF,$26,
  516. $81,$3D,$54,$48,$75,$0D,$AF,$26,$80,$3D,$3D,$75,$06,$47,$89,
  517. $3E,$8C,$04,$4F,$AE,$75,$DF,$AF,$B4,$3E,$BB,$13,$00,$CD,$21,
  518. $B4,$3E,$BB,$12,$00,$CD,$21,$06,$57,$31,$C9,$74,$12,$B0,$6E,
  519. $BA,$7E,$05,$E9,$5E,$03,$09,$C9,$75,$F4,$41,$E8,$A1,$03,$72,
  520. $EE,$B8,$87,$16,$CD,$2F,$09,$C0,$75,$ED,$80,$E3,$01,$74,$E8,
  521. $89,$3E,$00,$06,$8C,$06,$02,$06,$89,$36,$04,$06,$5F,$07,$E8,
  522. $D3,$02,$89,$3E,$2A,$00,$89,$36,$62,$07,$80,$3E,$2C,$00,$00,
  523. $74,$23,$B9,$08,$00,$BF,$2C,$00,$8A,$05,$47,$08,$C0,$74,$05,
  524. $88,$07,$43,$E2,$F4,$66,$C7,$07,$2E,$45,$58,$45,$83,$C3,$04,
  525. $C6,$07,$00,$89,$1E,$62,$07,$B8,$00,$3D,$BA,$64,$07,$CD,$21,
  526. $0F,$82,$B3,$02,$A3,$06,$06,$89,$C3,$B9,$06,$00,$BA,$B5,$07,
  527. $B4,$3F,$CD,$21,$31,$D2,$31,$C9,$A1,$B5,$07,$3D,$4C,$01,$74,
  528. $1B,$3D,$4D,$5A,$0F,$85,$98,$02,$8B,$16,$B9,$07,$C1,$E2,$09,
  529. $8B,$1E,$B7,$07,$09,$DB,$74,$05,$80,$EE,$02,$01,$DA,$89,$16,
  530. $BB,$07,$89,$0E,$BD,$07,$B8,$00,$42,$8B,$1E,$06,$06,$CD,$21,
  531. $B9,$A8,$00,$BA,$BF,$07,$B4,$3F,$CD,$21,$3D,$A8,$00,$75,$06,
  532. $81,$3E,$BF,$07,$4C,$01,$0F,$85,$61,$02,$66,$A1,$E3,$07,$66,
  533. $A3,$10,$06,$66,$8B,$0E,$BB,$07,$66,$A1,$03,$08,$66,$01,$C8,
  534. $66,$A3,$08,$06,$66,$A1,$2B,$08,$66,$01,$C8,$66,$A3,$0C,$06,
  535. $66,$8B,$1E,$4B,$08,$66,$A1,$4F,$08,$66,$01,$C3,$66,$B8,$01,
  536. $00,$01,$00,$66,$39,$C3,$73,$03,$66,$89,$C3,$66,$81,$C3,$FF,
  537. $FF,$00,$00,$31,$DB,$66,$89,$1E,$1C,$00,$E8,$F5,$02,$8B,$1E,
  538. $04,$06,$09,$DB,$74,$0A,$B4,$48,$CD,$21,$0F,$82,$15,$02,$8E,
  539. $C0,$E8,$08,$03,$B8,$01,$00,$FF,$1E,$00,$06,$0F,$82,$0F,$02,
  540. $8C,$06,$26,$00,$8C,$0E,$28,$00,$8C,$D8,$A3,$22,$00,$8E,$C0,
  541. $31,$C0,$B9,$01,$00,$CD,$31,$72,$07,$A3,$14,$06,$31,$C0,$CD,
  542. $31,$0F,$82,$F3,$01,$A3,$16,$06,$66,$8B,$0E,$1C,$00,$B8,$01,
  543. $05,$8B,$1E,$1E,$00,$CD,$31,$0F,$82,$E5,$01,$89,$1E,$1A,$06,
  544. $89,$0E,$18,$06,$89,$36,$1A,$00,$89,$3E,$18,$00,$B8,$07,$00,
  545. $8B,$1E,$14,$06,$8B,$0E,$1A,$06,$8B,$16,$18,$06,$CD,$31,$B8,
  546. $09,$00,$8C,$C9,$83,$E1,$03,$C1,$E1,$05,$51,$81,$C9,$9B,$C0,
  547. $CD,$31,$B8,$08,$00,$8B,$0E,$1E,$00,$49,$BA,$FF,$FF,$CD,$31,
  548. $B8,$07,$00,$8B,$1E,$16,$06,$8B,$0E,$1A,$06,$8B,$16,$18,$06,
  549. $CD,$31,$B8,$09,$00,$59,$81,$C9,$93,$C0,$CD,$31,$B8,$08,$00,
  550. $8B,$0E,$1E,$00,$49,$BA,$FF,$FF,$CD,$31,$B8,$00,$01,$BB,$00,
  551. $0F,$CD,$31,$73,$10,$3D,$08,$00,$0F,$85,$73,$01,$B8,$00,$01,
  552. $CD,$31,$0F,$82,$6A,$01,$A3,$1C,$06,$89,$16,$1E,$06,$C1,$E3,
  553. $04,$89,$1E,$20,$06,$66,$8B,$36,$08,$06,$66,$8B,$3E,$FB,$07,
  554. $66,$8B,$0E,$FF,$07,$E8,$49,$00,$66,$8B,$36,$0C,$06,$66,$8B,
  555. $3E,$23,$08,$66,$8B,$0E,$27,$08,$E8,$37,$00,$8E,$06,$16,$06,
  556. $66,$8B,$3E,$4B,$08,$66,$8B,$0E,$4F,$08,$66,$31,$C0,$66,$C1,
  557. $E9,$02,$67,$F3,$66,$AB,$B4,$3E,$8B,$1E,$06,$06,$CD,$21,$B8,
  558. $01,$01,$8B,$16,$1E,$06,$CD,$31,$1E,$0F,$A1,$8E,$1E,$16,$06,
  559. $66,$64,$FF,$2E,$10,$06,$66,$89,$F0,$66,$25,$FF,$01,$00,$00,
  560. $66,$01,$C1,$29,$C6,$66,$29,$C7,$66,$89,$0E,$26,$06,$66,$89,
  561. $3E,$22,$06,$E8,$0F,$01,$89,$36,$3E,$06,$66,$C1,$EE,$10,$89,
  562. $36,$42,$06,$8B,$1E,$06,$06,$89,$1E,$3A,$06,$C7,$06,$46,$06,
  563. $00,$42,$E8,$03,$01,$A1,$1C,$06,$A3,$4E,$06,$C7,$06,$3E,$06,
  564. $00,$00,$C6,$06,$47,$06,$3F,$A1,$28,$06,$09,$C0,$75,$09,$A1,
  565. $26,$06,$3B,$06,$20,$06,$76,$03,$A1,$20,$06,$A3,$42,$06,$E8,
  566. $D9,$00,$66,$31,$C9,$8B,$0E,$46,$06,$66,$8B,$3E,$22,$06,$66,
  567. $01,$0E,$22,$06,$66,$29,$0E,$26,$06,$66,$31,$F6,$C1,$E9,$02,
  568. $1E,$06,$8E,$06,$16,$06,$8E,$1E,$1E,$06,$67,$F3,$66,$A5,$07,
  569. $1F,$66,$03,$0E,$26,$06,$75,$AF,$C3,$3C,$3A,$74,$06,$3C,$2F,
  570. $74,$02,$3C,$5C,$C3,$BE,$64,$07,$89,$F3,$26,$8A,$05,$47,$88,
  571. $04,$38,$E0,$74,$0E,$08,$C0,$74,$0A,$46,$E8,$DE,$FF,$75,$EC,
  572. $89,$F3,$74,$E8,$C3,$B0,$66,$BA,$48,$05,$EB,$0C,$B0,$67,$BA,
  573. $55,$05,$EB,$05,$B0,$68,$BA,$5F,$05,$52,$8B,$1E,$62,$07,$C6,
  574. $07,$24,$BB,$64,$07,$EB,$28,$E8,$F5,$00,$B0,$69,$BA,$99,$05,
  575. $EB,$1A,$B0,$6A,$BA,$B2,$05,$EB,$13,$B0,$6B,$BA,$C4,$05,$EB,
  576. $0C,$B0,$6C,$BA,$D6,$05,$EB,$05,$B0,$69,$BA,$99,$05,$52,$BB,
  577. $3B,$05,$E8,$15,$00,$5B,$E8,$11,$00,$BB,$67,$04,$E8,$0B,$00,
  578. $B4,$4C,$CD,$21,$43,$50,$B4,$02,$CD,$21,$58,$8A,$17,$80,$FA,
  579. $24,$75,$F2,$C3,$0D,$0A,$24,$50,$51,$57,$31,$C0,$BF,$2A,$06,
  580. $B9,$19,$00,$F3,$AB,$5F,$59,$58,$C3,$B8,$00,$03,$BB,$21,$00,
  581. $31,$C9,$66,$BF,$2A,$06,$00,$00,$CD,$31,$C3,$00,$00,$30,$E4,
  582. $E8,$4E,$FF,$89,$DE,$8B,$3E,$8C,$04,$EB,$17,$B4,$3B,$E8,$41,
  583. $FF,$81,$FE,$64,$07,$74,$12,$8A,$44,$FF,$E8,$2A,$FF,$74,$04,
  584. $C6,$04,$5C,$46,$E8,$03,$00,$72,$E4,$C3,$E8,$34,$00,$BB,$44,
  585. $00,$8A,$07,$88,$04,$43,$46,$08,$C0,$75,$F6,$06,$57,$1E,$07,
  586. $E8,$9B,$FF,$BB,$2A,$06,$8C,$5F,$04,$89,$5F,$02,$BA,$64,$07,
  587. $B8,$00,$4B,$CD,$21,$5F,$07,$72,$09,$B4,$4D,$CD,$21,$2D,$00,
  588. $03,$F7,$D8,$EB,$28,$80,$3E,$69,$08,$05,$72,$20,$B8,$00,$58,
  589. $CD,$21,$A2,$67,$08,$B8,$02,$58,$CD,$21,$A2,$68,$08,$B8,$01,
  590. $58,$BB,$80,$00,$CD,$21,$B8,$03,$58,$BB,$01,$00,$CD,$21,$C3,
  591. $9C,$80,$3E,$69,$08,$05,$72,$1A,$50,$53,$B8,$03,$58,$8A,$1E,
  592. $68,$08,$30,$FF,$CD,$21,$B8,$01,$58,$8A,$1E,$67,$08,$30,$FF,
  593. $CD,$21,$5B,$58,$9D,$C3,$4C,$6F,$61,$64,$20,$65,$72,$72,$6F,
  594. $72,$3A,$20,$24,$3A,$20,$63,$61,$6E,$27,$74,$20,$6F,$70,$65,
  595. $6E,$24,$3A,$20,$6E,$6F,$74,$20,$45,$58,$45,$24,$3A,$20,$6E,
  596. $6F,$74,$20,$43,$4F,$46,$46,$20,$28,$43,$68,$65,$63,$6B,$20,
  597. $66,$6F,$72,$20,$76,$69,$72,$75,$73,$65,$73,$29,$24,$6E,$6F,
  598. $20,$44,$50,$4D,$49,$20,$2D,$20,$47,$65,$74,$20,$63,$73,$64,
  599. $70,$6D,$69,$2A,$62,$2E,$7A,$69,$70,$24,$6E,$6F,$20,$44,$4F,
  600. $53,$20,$6D,$65,$6D,$6F,$72,$79,$24,$6E,$65,$65,$64,$20,$44,
  601. $4F,$53,$20,$33,$24,$63,$61,$6E,$27,$74,$20,$73,$77,$69,$74,
  602. $63,$68,$20,$6D,$6F,$64,$65,$24,$6E,$6F,$20,$44,$50,$4D,$49,
  603. $20,$73,$65,$6C,$65,$63,$74,$6F,$72,$73,$24,$6E,$6F,$20,$44,
  604. $50,$4D,$49,$20,$6D,$65,$6D,$6F,$72,$79,$24,$90,$90,$90,$90,
  605. $90,$90,$90,$90,$90,$90,$90,$90,$90,$90,$90,$90,$90,$90,$90,
  606. $90,$90,$90,$90,$90,$90,$90,$90);
  607. const win32stub : array[0..127] of byte=(
  608. $4D,$5A,$90,$00,$03,$00,$00,$00,$04,$00,$00,$00,$FF,$FF,$00,$00,
  609. $B8,$00,$00,$00,$00,$00,$00,$00,$40,$00,$00,$00,$00,$00,$00,$00,
  610. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  611. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$80,$00,$00,$00,
  612. $0E,$1F,$BA,$0E,$00,$B4,$09,$CD,$21,$B8,$01,$4C,$CD,$21,$54,$68,
  613. $69,$73,$20,$70,$72,$6F,$67,$72,$61,$6D,$20,$63,$61,$6E,$6E,$6F,
  614. $74,$20,$62,$65,$20,$72,$75,$6E,$20,$69,$6E,$20,$44,$4F,$53,$20,
  615. $6D,$6F,$64,$65,$2E,$0D,$0D,$0A,$24,$00,$00,$00,$00,$00,$00,$00);
  616. const pemagic : array[0..3] of byte = (
  617. $50,$45,$00,$00);
  618. {****************************************************************************
  619. Helpers
  620. ****************************************************************************}
  621. function djencodesechdrflags(aoptions:TObjSectionOptions):longword;
  622. begin
  623. if (oso_load in aoptions) then
  624. begin
  625. if oso_executable in aoptions then
  626. result:=COFF_STYP_TEXT
  627. else if not(oso_data in aoptions) then
  628. result:=COFF_STYP_BSS
  629. else
  630. result:=COFF_STYP_DATA;
  631. end
  632. else
  633. result:=COFF_STYP_REG;
  634. end;
  635. function djdecodesechdrflags(const aname:string;flags:longword):TObjSectionOptions;
  636. begin
  637. result:=[];
  638. if flags and COFF_STYP_TEXT<>0 then
  639. result:=[oso_data,oso_load,oso_executable]
  640. else if flags and COFF_STYP_BSS<>0 then
  641. result:=[oso_load]
  642. else if flags and COFF_STYP_DATA<>0 then
  643. result:=[oso_data,oso_load]
  644. else
  645. result:=[oso_data]
  646. end;
  647. function peencodesechdrflags(aoptions:TObjSectionOptions;aalign:shortint):longword;
  648. begin
  649. result:=0;
  650. if (oso_load in aoptions) then
  651. begin
  652. if oso_executable in aoptions then
  653. result:=result or PE_SCN_CNT_CODE or PE_SCN_MEM_EXECUTE
  654. else
  655. begin
  656. if (oso_data in aoptions) then
  657. result:=result or PE_SCN_CNT_INITIALIZED_DATA
  658. else
  659. result:=result or PE_SCN_CNT_UNINITIALIZED_DATA;
  660. end;
  661. if oso_write in aoptions then
  662. result:=result or PE_SCN_MEM_WRITE or PE_SCN_MEM_READ
  663. else
  664. result:=result or PE_SCN_MEM_READ;
  665. end
  666. else
  667. result:=result or PE_SCN_MEM_DISCARDABLE;
  668. case aalign of
  669. 1 : result:=result or PE_SCN_ALIGN_1BYTES;
  670. 2 : result:=result or PE_SCN_ALIGN_2BYTES;
  671. 4 : result:=result or PE_SCN_ALIGN_4BYTES;
  672. 8 : result:=result or PE_SCN_ALIGN_8BYTES;
  673. 16 : result:=result or PE_SCN_ALIGN_16BYTES;
  674. 32 : result:=result or PE_SCN_ALIGN_32BYTES;
  675. 64 : result:=result or PE_SCN_ALIGN_64BYTES;
  676. else result:=result or PE_SCN_ALIGN_16BYTES;
  677. end;
  678. end;
  679. procedure pedecodesechdrflags(const aname:string;flags:longword;out aoptions:TObjSectionOptions;out aalign:shortint);
  680. var
  681. alignflag : longword;
  682. begin
  683. aoptions:=[];
  684. if flags and PE_SCN_CNT_CODE<>0 then
  685. include(aoptions,oso_executable);
  686. if flags and PE_SCN_MEM_DISCARDABLE<>0 then
  687. include(aoptions,oso_debug);
  688. if flags and PE_SCN_CNT_UNINITIALIZED_DATA=0 then
  689. include(aoptions,oso_data);
  690. if (flags and PE_SCN_LNK_REMOVE<>0) or
  691. (flags and PE_SCN_MEM_DISCARDABLE<>0) then
  692. include(aoptions,oso_noload)
  693. else
  694. include(aoptions,oso_load);
  695. { read/write }
  696. if flags and PE_SCN_MEM_WRITE<>0 then
  697. include(aoptions,oso_write)
  698. else
  699. include(aoptions,oso_readonly);
  700. { alignment }
  701. alignflag:=flags and PE_SCN_ALIGN_MASK;
  702. if alignflag=PE_SCN_ALIGN_64BYTES then
  703. aalign:=64
  704. else if alignflag=PE_SCN_ALIGN_32BYTES then
  705. aalign:=32
  706. else if alignflag=PE_SCN_ALIGN_16BYTES then
  707. aalign:=16
  708. else if alignflag=PE_SCN_ALIGN_8BYTES then
  709. aalign:=8
  710. else if alignflag=PE_SCN_ALIGN_4BYTES then
  711. aalign:=4
  712. else if alignflag=PE_SCN_ALIGN_2BYTES then
  713. aalign:=2
  714. else if alignflag=PE_SCN_ALIGN_1BYTES then
  715. aalign:=1
  716. else if alignflag=0 then
  717. aalign:=0
  718. else
  719. Internalerror(2009050401);
  720. end;
  721. {****************************************************************************
  722. TCoffObjSection
  723. ****************************************************************************}
  724. constructor TCoffObjSection.create(AList:TFPHashObjectList;const aname:string;aalign:shortint;aoptions:TObjSectionOptions);
  725. begin
  726. inherited create(AList,aname,aalign,aoptions);
  727. end;
  728. procedure TCoffObjSection.addsymsizereloc(ofs:aword;p:TObjSymbol;symsize:aword;reloctype:TObjRelocationType);
  729. begin
  730. ObjRelocations.Add(TObjRelocation.createsymbolsize(ofs,p,symsize,reloctype));
  731. end;
  732. procedure TCoffObjSection.fixuprelocs;
  733. var
  734. i,zero,address_size : longint;
  735. objreloc : TObjRelocation;
  736. address,
  737. relocval : aint;
  738. relocsec : TObjSection;
  739. {$ifdef x86_64}
  740. s : string;
  741. {$endif x86_64}
  742. begin
  743. if (ObjRelocations.Count>0) and
  744. not assigned(data) then
  745. internalerror(200205183);
  746. for i:=0 to ObjRelocations.Count-1 do
  747. begin
  748. objreloc:=TObjRelocation(ObjRelocations[i]);
  749. address_size:=4;
  750. case objreloc.typ of
  751. RELOC_NONE:
  752. continue;
  753. RELOC_ZERO:
  754. begin
  755. data.Seek(objreloc.dataoffset);
  756. zero:=0;
  757. data.Write(zero,4);
  758. continue;
  759. end;
  760. {$ifdef x86_64}
  761. RELOC_ABSOLUTE:
  762. address_size:=8;
  763. {$endif x86_64}
  764. end;
  765. address:=0;
  766. data.Seek(objreloc.dataoffset);
  767. data.Read(address,address_size);
  768. if assigned(objreloc.symbol) then
  769. begin
  770. relocsec:=objreloc.symbol.objsection;
  771. relocval:=objreloc.symbol.address;
  772. end
  773. else
  774. if assigned(objreloc.objsection) then
  775. begin
  776. relocsec:=objreloc.objsection;
  777. relocval:=objreloc.objsection.mempos
  778. end
  779. else
  780. internalerror(200205183);
  781. { Only debug sections are allowed to have relocs pointing to unused sections }
  782. if not relocsec.used and not (oso_debug in secoptions) then
  783. internalerror(200603061);
  784. if relocsec.used then
  785. case objreloc.typ of
  786. RELOC_RELATIVE :
  787. begin
  788. address:=address-mempos+relocval;
  789. if TCoffObjData(objdata).win32 then
  790. dec(address,objreloc.dataoffset+4);
  791. end;
  792. RELOC_RVA:
  793. begin
  794. { fixup address when the symbol was known in defined object }
  795. if (relocsec.objdata=objdata) then
  796. dec(address,TCoffObjSection(relocsec).orgmempos);
  797. {$ifdef arm}
  798. if (relocsec.objdata=objdata) and not TCoffObjData(objdata).eVCobj then
  799. inc(address, relocsec.MemPos)
  800. else
  801. {$endif arm}
  802. inc(address,relocval);
  803. end;
  804. RELOC_SECREL32 :
  805. begin
  806. { fixup address when the symbol was known in defined object }
  807. if (relocsec.objdata=objdata) then
  808. dec(address,relocsec.ExeSection.MemPos);
  809. inc(address,relocval);
  810. end;
  811. {$ifdef arm}
  812. RELOC_RELATIVE_24:
  813. begin
  814. relocval:=longint(relocval - mempos - objreloc.dataoffset) shr 2 - 2;
  815. address:=address or (relocval and $ffffff);
  816. relocval:=relocval shr 24;
  817. if (relocval<>$3f) and (relocval<>0) then
  818. internalerror(200606085); { offset overflow }
  819. end;
  820. {$endif arm}
  821. {$ifdef x86_64}
  822. { 64 bit coff only }
  823. RELOC_RELATIVE_1:
  824. begin
  825. address:=address-mempos+relocval;
  826. dec(address,objreloc.dataoffset+1);
  827. end;
  828. RELOC_RELATIVE_2:
  829. begin
  830. address:=address-mempos+relocval;
  831. dec(address,objreloc.dataoffset+2);
  832. end;
  833. RELOC_RELATIVE_3:
  834. begin
  835. address:=address-mempos+relocval;
  836. dec(address,objreloc.dataoffset+3);
  837. end;
  838. RELOC_RELATIVE_4:
  839. begin
  840. address:=address-mempos+relocval;
  841. dec(address,objreloc.dataoffset+4);
  842. end;
  843. RELOC_RELATIVE_5:
  844. begin
  845. address:=address-mempos+relocval;
  846. dec(address,objreloc.dataoffset+5);
  847. end;
  848. RELOC_ABSOLUTE32,
  849. {$endif x86_64}
  850. RELOC_ABSOLUTE :
  851. begin
  852. if oso_common in relocsec.secoptions then
  853. dec(address,objreloc.orgsize)
  854. else
  855. begin
  856. { fixup address when the symbol was known in defined object }
  857. if (relocsec.objdata=objdata) then
  858. dec(address,TCoffObjSection(relocsec).orgmempos);
  859. end;
  860. {$ifdef arm}
  861. if (relocsec.objdata=objdata) and not TCoffObjData(objdata).eVCobj then
  862. inc(address, relocsec.MemPos)
  863. else
  864. {$endif arm}
  865. inc(address,relocval);
  866. inc(address,relocsec.objdata.imagebase);
  867. end;
  868. else
  869. internalerror(200604014);
  870. end
  871. else
  872. address:=0; { Relocation in debug section points to unused section, which is eliminated by linker }
  873. data.Seek(objreloc.dataoffset);
  874. data.Write(address,address_size);
  875. {$ifdef x86_64}
  876. if objreloc.typ = RELOC_ABSOLUTE32 then begin
  877. if assigned(objreloc.symbol) then
  878. s:=objreloc.symbol.Name
  879. else
  880. s:=objreloc.objsection.Name;
  881. Message2(link_w_32bit_absolute_reloc, ObjData.Name, s);
  882. end;
  883. {$endif x86_64}
  884. end;
  885. end;
  886. {****************************************************************************
  887. TDJCoffObjSection
  888. ****************************************************************************}
  889. constructor TDJCoffObjSection.create(AList:TFPHashObjectList;const aname:string;aalign:shortint;aoptions:TObjSectionOptions);
  890. begin
  891. inherited create(alist,aname,aalign,aoptions);
  892. end;
  893. {****************************************************************************
  894. TPECoffObjSection
  895. ****************************************************************************}
  896. constructor TPECoffObjSection.create(AList:TFPHashObjectList;const aname:string;aalign:shortint;aoptions:TObjSectionOptions);
  897. begin
  898. inherited create(alist,aname,aalign,aoptions);
  899. end;
  900. {****************************************************************************
  901. TCoffObjData
  902. ****************************************************************************}
  903. constructor TCoffObjData.createcoff(const n:string;awin32:boolean;acObjSection:TObjSectionClass);
  904. begin
  905. inherited create(n);
  906. CObjSection:=ACObjSection;
  907. win32:=awin32;
  908. { we need at least the following 3 ObjSections }
  909. createsection(sec_code);
  910. createsection(sec_data);
  911. createsection(sec_bss);
  912. end;
  913. destructor TCoffObjData.destroy;
  914. begin
  915. inherited destroy;
  916. end;
  917. function TCoffObjData.sectionname(atype:TAsmSectiontype;const aname:string;aorder:TAsmSectionOrder):string;
  918. var
  919. sep : string[3];
  920. secname : string;
  921. begin
  922. secname:=coffsecnames[atype];
  923. if create_smartlink_sections and
  924. (aname<>'') then
  925. begin
  926. case aorder of
  927. secorder_begin :
  928. sep:='.b_';
  929. secorder_end :
  930. sep:='.z_';
  931. else
  932. sep:='.n_';
  933. end;
  934. result:=secname+sep+aname
  935. end
  936. else
  937. result:=secname;
  938. end;
  939. procedure TCoffObjData.CreateDebugSections;
  940. begin
  941. if target_dbg.id=dbg_stabs then
  942. begin
  943. stabssec:=createsection(sec_stab);
  944. stabstrsec:=createsection(sec_stabstr);
  945. end;
  946. end;
  947. procedure TCoffObjData.writereloc(data:aint;len:aword;p:TObjSymbol;reloctype:TObjRelocationType);
  948. var
  949. curraddr,
  950. symaddr : aword;
  951. begin
  952. if CurrObjSec=nil then
  953. internalerror(200403072);
  954. if assigned(p) then
  955. begin
  956. { current address }
  957. curraddr:=CurrObjSec.mempos+CurrObjSec.Size;
  958. { external/common symbols don't have a fixed memory position yet }
  959. if (p.bind=AB_COMMON) then
  960. begin
  961. { For go32v2 we need to use the size as address }
  962. if not win32 then
  963. symaddr:=p.size
  964. else
  965. symaddr:=0;
  966. end
  967. else
  968. symaddr:=p.address;
  969. { no symbol relocation need inside a section }
  970. if (p.objsection=CurrObjSec) and
  971. (p.bind<>AB_COMMON) then
  972. begin
  973. case reloctype of
  974. RELOC_ABSOLUTE :
  975. begin
  976. CurrObjSec.addsectionreloc(curraddr,CurrObjSec,RELOC_ABSOLUTE);
  977. inc(data,symaddr);
  978. end;
  979. {$ifdef x86_64}
  980. RELOC_ABSOLUTE32 :
  981. begin
  982. CurrObjSec.addsectionreloc(curraddr,CurrObjSec,RELOC_ABSOLUTE32);
  983. inc(data,symaddr);
  984. end;
  985. {$endif x86_64}
  986. RELOC_RELATIVE :
  987. begin
  988. inc(data,symaddr-len-CurrObjSec.Size);
  989. end;
  990. RELOC_RVA :
  991. begin
  992. CurrObjSec.addsectionreloc(curraddr,CurrObjSec,RELOC_RVA);
  993. inc(data,symaddr);
  994. end;
  995. else
  996. internalerror(200604013);
  997. end;
  998. end
  999. else
  1000. begin
  1001. if (p.objsection<>nil) and
  1002. (p.bind<>AB_COMMON) and
  1003. (reloctype<>RELOC_RELATIVE) then
  1004. CurrObjSec.addsectionreloc(curraddr,p.objsection,reloctype)
  1005. else
  1006. CurrObjSec.addsymreloc(curraddr,p,reloctype);
  1007. if (not win32) or
  1008. ((reloctype<>RELOC_RELATIVE) and (p.objsection<>nil)) then
  1009. inc(data,symaddr);
  1010. if reloctype=RELOC_RELATIVE then
  1011. begin
  1012. if win32 then
  1013. dec(data,len-4)
  1014. else
  1015. dec(data,len+CurrObjSec.Size);
  1016. end;
  1017. end;
  1018. end
  1019. else
  1020. begin
  1021. if reloctype=RELOC_RVA then
  1022. internalerror(200603033);
  1023. end;
  1024. CurrObjSec.write(data,len);
  1025. end;
  1026. procedure TCoffObjData.afteralloc;
  1027. var
  1028. mempos : qword;
  1029. i : longint;
  1030. begin
  1031. inherited afteralloc;
  1032. { DJ Coff requires mempositions }
  1033. if not win32 then
  1034. begin
  1035. mempos:=0;
  1036. for i:=0 to ObjSectionList.Count-1 do
  1037. mempos:=TObjSection(ObjSectionList[i]).setmempos(mempos);
  1038. end;
  1039. end;
  1040. {****************************************************************************
  1041. TDJCoffObjData
  1042. ****************************************************************************}
  1043. constructor TDJCoffObjData.create(const n:string);
  1044. begin
  1045. inherited createcoff(n,false,TDJCoffObjSection);
  1046. end;
  1047. {****************************************************************************
  1048. TPECoffObjData
  1049. ****************************************************************************}
  1050. constructor TPECoffObjData.create(const n:string);
  1051. begin
  1052. inherited createcoff(n,true,TPECoffObjSection);
  1053. end;
  1054. {****************************************************************************
  1055. TCoffObjOutput
  1056. ****************************************************************************}
  1057. constructor TCoffObjOutput.createcoff(AWriter:TObjectWriter;awin32:boolean);
  1058. begin
  1059. inherited create(AWriter);
  1060. win32:=awin32;
  1061. end;
  1062. destructor TCoffObjOutput.destroy;
  1063. begin
  1064. if assigned(FCoffSyms) then
  1065. FCoffSyms.free;
  1066. if assigned(FCoffStrs) then
  1067. FCoffStrs.free;
  1068. inherited destroy;
  1069. end;
  1070. procedure TCoffObjOutput.write_symbol(const name:string;value:aword;section:smallint;typ,aux:byte);
  1071. var
  1072. sym : coffsymbol;
  1073. begin
  1074. FillChar(sym,sizeof(sym),0);
  1075. { symbolname }
  1076. if length(name)>8 then
  1077. begin
  1078. sym.strpos:=FCoffStrs.size+4;
  1079. FCoffStrs.writestr(name);
  1080. FCoffStrs.writestr(#0);
  1081. end
  1082. else
  1083. move(name[1],sym.name,length(name));
  1084. sym.value:=value;
  1085. sym.section:=section;
  1086. sym.typ:=typ;
  1087. sym.aux:=aux;
  1088. inc(symidx);
  1089. FCoffSyms.write(sym,sizeof(sym));
  1090. end;
  1091. procedure TCoffObjOutput.section_write_symbol(p:TObject;arg:pointer);
  1092. var
  1093. secrec : coffsectionrec;
  1094. begin
  1095. with TCoffObjSection(p) do
  1096. begin
  1097. secidx:=symidx div 2;
  1098. secsymidx:=symidx;
  1099. write_symbol(name,mempos,secidx,COFF_SYM_SECTION,1);
  1100. { AUX }
  1101. fillchar(secrec,sizeof(secrec),0);
  1102. secrec.len:=Size;
  1103. secrec.nrelocs:=ObjRelocations.count;
  1104. inc(symidx);
  1105. FCoffSyms.write(secrec,sizeof(secrec));
  1106. end;
  1107. end;
  1108. procedure TCoffObjOutput.section_write_relocs(p:TObject;arg:pointer);
  1109. var
  1110. i : longint;
  1111. rel : coffreloc;
  1112. objreloc : TObjRelocation;
  1113. begin
  1114. for i:=0 to TObjSection(p).ObjRelocations.Count-1 do
  1115. begin
  1116. objreloc:=TObjRelocation(TObjSection(p).ObjRelocations[i]);
  1117. rel.address:=objreloc.dataoffset;
  1118. if assigned(objreloc.symbol) then
  1119. begin
  1120. if (objreloc.symbol.bind=AB_LOCAL) then
  1121. rel.sym:=objreloc.symbol.objsection.secsymidx
  1122. else
  1123. begin
  1124. if objreloc.symbol.symidx=-1 then
  1125. internalerror(200602233);
  1126. rel.sym:=objreloc.symbol.symidx;
  1127. end;
  1128. end
  1129. else
  1130. begin
  1131. if objreloc.objsection<>nil then
  1132. rel.sym:=objreloc.objsection.secsymidx
  1133. else
  1134. rel.sym:=0;
  1135. end;
  1136. case objreloc.typ of
  1137. {$ifdef arm}
  1138. RELOC_ABSOLUTE :
  1139. rel.reloctype:=IMAGE_REL_ARM_ADDR32;
  1140. { I've no idea if this is correct (FK):
  1141. RELOC_RELATIVE :
  1142. rel.reloctype:=IMAGE_REL_ARM_GPREL12;
  1143. }
  1144. RELOC_RVA :
  1145. rel.reloctype:=IMAGE_REL_ARM_ADDR32NB;
  1146. RELOC_SECREL32 :
  1147. rel.reloctype:=IMAGE_REL_ARM_SECREL;
  1148. {$endif arm}
  1149. {$ifdef i386}
  1150. RELOC_RELATIVE :
  1151. rel.reloctype:=IMAGE_REL_I386_PCRLONG;
  1152. RELOC_ABSOLUTE :
  1153. rel.reloctype:=IMAGE_REL_I386_DIR32;
  1154. RELOC_RVA :
  1155. rel.reloctype:=IMAGE_REL_I386_IMAGEBASE;
  1156. RELOC_SECREL32 :
  1157. rel.reloctype:=IMAGE_REL_I386_SECREL32;
  1158. {$endif i386}
  1159. {$ifdef x86_64}
  1160. RELOC_RELATIVE :
  1161. rel.reloctype:=IMAGE_REL_AMD64_REL32;
  1162. RELOC_ABSOLUTE32 :
  1163. rel.reloctype:=IMAGE_REL_AMD64_ADDR32;
  1164. RELOC_ABSOLUTE :
  1165. rel.reloctype:=IMAGE_REL_AMD64_ADDR64;
  1166. RELOC_RVA :
  1167. rel.reloctype:=IMAGE_REL_AMD64_ADDR32NB;
  1168. RELOC_RELATIVE_1 :
  1169. rel.reloctype:=IMAGE_REL_AMD64_REL32_1;
  1170. RELOC_RELATIVE_2 :
  1171. rel.reloctype:=IMAGE_REL_AMD64_REL32_2;
  1172. RELOC_RELATIVE_3 :
  1173. rel.reloctype:=IMAGE_REL_AMD64_REL32_3;
  1174. RELOC_RELATIVE_4 :
  1175. rel.reloctype:=IMAGE_REL_AMD64_REL32_4;
  1176. RELOC_RELATIVE_5 :
  1177. rel.reloctype:=IMAGE_REL_AMD64_REL32_5;
  1178. RELOC_SECREL32 :
  1179. rel.reloctype:=IMAGE_REL_AMD64_SECREL;
  1180. {$endif x86_64}
  1181. else
  1182. internalerror(200905071);
  1183. end;
  1184. FWriter.write(rel,sizeof(rel));
  1185. end;
  1186. end;
  1187. procedure TCoffObjOutput.create_symbols(data:TObjData);
  1188. var
  1189. filename : string[18];
  1190. sectionval : word;
  1191. globalval : byte;
  1192. i : longint;
  1193. value : aword;
  1194. objsym : TObjSymbol;
  1195. begin
  1196. with TCoffObjData(data) do
  1197. begin
  1198. symidx:=0;
  1199. { The `.file' record, and the file name auxiliary record }
  1200. write_symbol('.file', 0, -2, COFF_SYM_FILE, 1);
  1201. fillchar(filename,sizeof(filename),0);
  1202. filename:=ExtractFileName(current_module.mainsource^);
  1203. inc(symidx);
  1204. FCoffSyms.write(filename[1],sizeof(filename)-1);
  1205. { Sections }
  1206. ObjSectionList.ForEachCall(@section_write_symbol,nil);
  1207. { ObjSymbols }
  1208. for i:=0 to ObjSymbolList.Count-1 do
  1209. begin
  1210. objsym:=TObjSymbol(ObjSymbolList[i]);
  1211. if (objsym.typ=AT_LABEL) and (objsym.bind=AB_LOCAL) then
  1212. continue;
  1213. case objsym.bind of
  1214. AB_GLOBAL :
  1215. begin
  1216. globalval:=2;
  1217. sectionval:=TCoffObjSection(objsym.objsection).secidx;
  1218. value:=objsym.address;
  1219. end;
  1220. AB_LOCAL :
  1221. begin
  1222. globalval:=3;
  1223. sectionval:=TCoffObjSection(objsym.objsection).secidx;
  1224. value:=objsym.address;
  1225. end;
  1226. else
  1227. begin
  1228. globalval:=2;
  1229. sectionval:=0;
  1230. value:=objsym.size;
  1231. end;
  1232. end;
  1233. { symbolname }
  1234. objsym.symidx:=symidx;
  1235. write_symbol(objsym.name,value,sectionval,globalval,0);
  1236. end;
  1237. end;
  1238. end;
  1239. procedure TCoffObjOutput.section_set_datapos(p:TObject;arg:pointer);
  1240. begin
  1241. TObjSection(p).setdatapos(paword(arg)^);
  1242. end;
  1243. procedure TCoffObjOutput.section_set_reloc_datapos(p:TObject;arg:pointer);
  1244. begin
  1245. TCoffObjSection(p).coffrelocpos:=paint(arg)^;
  1246. inc(paint(arg)^,sizeof(coffreloc)*TObjSection(p).ObjRelocations.count);
  1247. end;
  1248. procedure TCoffObjOutput.section_write_header(p:TObject;arg:pointer);
  1249. var
  1250. sechdr : tcoffsechdr;
  1251. s : string;
  1252. strpos : aword;
  1253. begin
  1254. with TCoffObjSection(p) do
  1255. begin
  1256. fillchar(sechdr,sizeof(sechdr),0);
  1257. s:=name;
  1258. if length(s)>8 then
  1259. begin
  1260. strpos:=FCoffStrs.size+4;
  1261. FCoffStrs.writestr(s);
  1262. FCoffStrs.writestr(#0);
  1263. s:='/'+ToStr(strpos);
  1264. end;
  1265. move(s[1],sechdr.name,length(s));
  1266. if not win32 then
  1267. begin
  1268. sechdr.rvaofs:=mempos;
  1269. sechdr.vsize:=mempos;
  1270. end
  1271. else
  1272. begin
  1273. if not(oso_data in secoptions) then
  1274. sechdr.vsize:=Size;
  1275. end;
  1276. sechdr.DataSize:=size;
  1277. if (Size>0) and
  1278. (oso_data in secoptions) then
  1279. sechdr.datapos:=datapos;
  1280. sechdr.nrelocs:=ObjRelocations.count;
  1281. sechdr.relocpos:=coffrelocpos;
  1282. if win32 then
  1283. sechdr.flags:=peencodesechdrflags(secoptions,secalign)
  1284. else
  1285. sechdr.flags:=djencodesechdrflags(secoptions);
  1286. FWriter.write(sechdr,sizeof(sechdr));
  1287. end;
  1288. end;
  1289. procedure TCoffObjOutput.section_write_data(p:TObject;arg:pointer);
  1290. begin
  1291. with TObjSection(p) do
  1292. begin
  1293. if assigned(data) then
  1294. begin
  1295. FWriter.writezeros(dataalignbytes);
  1296. if Datapos<>FWriter.ObjSize then
  1297. internalerror(200603052);
  1298. FWriter.writearray(data);
  1299. end;
  1300. end;
  1301. end;
  1302. function TCoffObjOutput.writedata(data:TObjData):boolean;
  1303. var
  1304. orgdatapos,
  1305. datapos,
  1306. sympos : aword;
  1307. i : longint;
  1308. gotreloc : boolean;
  1309. header : tcoffheader;
  1310. begin
  1311. result:=false;
  1312. FCoffSyms:=TDynamicArray.Create(SymbolMaxGrow);
  1313. FCoffStrs:=TDynamicArray.Create(StrsMaxGrow);
  1314. with TCoffObjData(data) do
  1315. begin
  1316. { Create Symbol Table }
  1317. create_symbols(data);
  1318. { Calculate the filepositions }
  1319. datapos:=sizeof(tcoffheader)+sizeof(tcoffsechdr)*ObjSectionList.Count;
  1320. { Sections first }
  1321. ObjSectionList.ForEachCall(@section_set_datapos,@datapos);
  1322. { relocs }
  1323. orgdatapos:=datapos;
  1324. ObjSectionList.ForEachCall(@section_set_reloc_datapos,@datapos);
  1325. gotreloc:=(orgdatapos<>datapos);
  1326. { Symbols }
  1327. sympos:=datapos;
  1328. { Generate COFF header }
  1329. fillchar(header,sizeof(tcoffheader),0);
  1330. header.mach:=COFF_MAGIC;
  1331. header.nsects:=ObjSectionList.Count;
  1332. header.sympos:=sympos;
  1333. header.syms:=symidx;
  1334. if win32 then
  1335. begin
  1336. {$ifdef arm}
  1337. header.flag:=PE_FILE_32BIT_MACHINE or
  1338. PE_FILE_LINE_NUMS_STRIPPED or PE_FILE_LOCAL_SYMS_STRIPPED;
  1339. {$else arm}
  1340. header.flag:=PE_FILE_BYTES_REVERSED_LO or PE_FILE_32BIT_MACHINE or
  1341. PE_FILE_LINE_NUMS_STRIPPED or PE_FILE_LOCAL_SYMS_STRIPPED;
  1342. {$endif arm}
  1343. if not gotreloc then
  1344. header.flag:=header.flag or PE_FILE_RELOCS_STRIPPED;
  1345. end
  1346. else
  1347. begin
  1348. header.flag:=COFF_FLAG_AR32WR or COFF_FLAG_NOLINES or COFF_FLAG_NOLSYMS;
  1349. if not gotreloc then
  1350. header.flag:=header.flag or COFF_FLAG_NORELOCS;
  1351. end;
  1352. FWriter.write(header,sizeof(header));
  1353. { Section headers }
  1354. ObjSectionList.ForEachCall(@section_write_header,nil);
  1355. { ObjSections }
  1356. ObjSectionList.ForEachCall(@section_write_data,nil);
  1357. { Relocs }
  1358. ObjSectionList.ForEachCall(@section_write_relocs,nil);
  1359. { ObjSymbols }
  1360. if Sympos<>FWriter.ObjSize then
  1361. internalerror(200603051);
  1362. FWriter.writearray(FCoffSyms);
  1363. { Strings }
  1364. i:=FCoffStrs.size+4;
  1365. FWriter.write(i,4);
  1366. FWriter.writearray(FCoffStrs);
  1367. end;
  1368. FCoffStrs.Free;
  1369. FCoffStrs:=nil;
  1370. FCoffSyms.Free;
  1371. FCoffSyms:=nil;
  1372. end;
  1373. constructor TDJCoffObjOutput.create(AWriter:TObjectWriter);
  1374. begin
  1375. inherited createcoff(AWriter,false);
  1376. cobjdata:=TDJCoffObjData;
  1377. end;
  1378. constructor TPECoffObjOutput.create(AWriter:TObjectWriter);
  1379. begin
  1380. inherited createcoff(AWriter,true);
  1381. cobjdata:=TPECoffObjData;
  1382. end;
  1383. {****************************************************************************
  1384. TCoffObjInput
  1385. ****************************************************************************}
  1386. constructor TCoffObjInput.createcoff(awin32:boolean);
  1387. begin
  1388. inherited create;
  1389. win32:=awin32;
  1390. FSymTbl:=nil;
  1391. end;
  1392. destructor TCoffObjInput.destroy;
  1393. begin
  1394. if assigned(FCoffSyms) then
  1395. FCoffSyms.free;
  1396. if assigned(FCoffStrs) then
  1397. FCoffStrs.free;
  1398. if assigned(FSymTbl) then
  1399. freemem(FSymTbl);
  1400. if assigned(FSecTbl) then
  1401. freemem(FSecTbl);
  1402. inherited destroy;
  1403. end;
  1404. function TCoffObjInput.GetSection(secidx:longint):TObjSection;
  1405. begin
  1406. result:=nil;
  1407. if (secidx<1) or (secidx>FSecCount) then
  1408. begin
  1409. InputError('Failed reading coff file, invalid section index');
  1410. exit;
  1411. end;
  1412. result:=FSecTbl^[secidx];
  1413. end;
  1414. function TCoffObjInput.Read_str(strpos:longword):string;
  1415. begin
  1416. FCoffStrs.Seek(strpos-4);
  1417. FCoffStrs.Read(result[1],255);
  1418. result[255]:=#0;
  1419. result[0]:=chr(strlen(@result[1]));
  1420. if result='' then
  1421. Internalerror(200205172);
  1422. end;
  1423. procedure TCoffObjInput.read_relocs(s:TCoffObjSection);
  1424. var
  1425. rel : coffreloc;
  1426. rel_type : TObjRelocationType;
  1427. i : longint;
  1428. p : TObjSymbol;
  1429. begin
  1430. for i:=1 to s.coffrelocs do
  1431. begin
  1432. FReader.read(rel,sizeof(rel));
  1433. case rel.reloctype of
  1434. {$ifdef arm}
  1435. IMAGE_REL_ARM_ABSOLUTE:
  1436. rel_type:=RELOC_NONE;
  1437. IMAGE_REL_ARM_ADDR32:
  1438. rel_type:=RELOC_ABSOLUTE;
  1439. IMAGE_REL_ARM_ADDR32NB:
  1440. rel_type:=RELOC_RVA;
  1441. IMAGE_REL_ARM_BRANCH24:
  1442. rel_type:=RELOC_RELATIVE_24;
  1443. {$endif arm}
  1444. {$ifdef i386}
  1445. IMAGE_REL_I386_PCRLONG :
  1446. rel_type:=RELOC_RELATIVE;
  1447. IMAGE_REL_I386_DIR32 :
  1448. rel_type:=RELOC_ABSOLUTE;
  1449. IMAGE_REL_I386_IMAGEBASE :
  1450. rel_type:=RELOC_RVA;
  1451. IMAGE_REL_I386_SECREL32 :
  1452. rel_type:=RELOC_SECREL32;
  1453. {$endif i386}
  1454. {$ifdef x86_64}
  1455. IMAGE_REL_AMD64_REL32:
  1456. rel_type:=RELOC_RELATIVE;
  1457. IMAGE_REL_AMD64_ADDR32:
  1458. rel_type:=RELOC_ABSOLUTE32;
  1459. IMAGE_REL_AMD64_ADDR64:
  1460. rel_type:=RELOC_ABSOLUTE;
  1461. IMAGE_REL_AMD64_ADDR32NB:
  1462. rel_type:=RELOC_RVA;
  1463. IMAGE_REL_AMD64_REL32_1:
  1464. rel_type:=RELOC_RELATIVE_1;
  1465. IMAGE_REL_AMD64_REL32_2:
  1466. rel_type:=RELOC_RELATIVE_2;
  1467. IMAGE_REL_AMD64_REL32_3:
  1468. rel_type:=RELOC_RELATIVE_3;
  1469. IMAGE_REL_AMD64_REL32_4:
  1470. rel_type:=RELOC_RELATIVE_4;
  1471. IMAGE_REL_AMD64_REL32_5:
  1472. rel_type:=RELOC_RELATIVE_5;
  1473. IMAGE_REL_AMD64_SECREL:
  1474. rel_type:=RELOC_SECREL32;
  1475. {$endif x86_64}
  1476. else
  1477. begin
  1478. InputError('Failed reading coff file, illegal reloctype $'+system.hexstr(rel.reloctype,4));
  1479. exit;
  1480. end;
  1481. end;
  1482. p:=FSymTbl^[rel.sym].sym;
  1483. if assigned(p) then
  1484. s.addsymsizereloc(rel.address-s.mempos,p,FSymTbl^[rel.sym].orgsize,rel_type)
  1485. else
  1486. begin
  1487. InputError('Failed reading coff file, can''t resolve symbol of relocation');
  1488. exit;
  1489. end;
  1490. end;
  1491. end;
  1492. procedure TCoffObjInput.read_symbols(objdata:TObjData);
  1493. var
  1494. size,
  1495. address,
  1496. nsyms,
  1497. symidx : aint;
  1498. i : longint;
  1499. sym : coffsymbol;
  1500. objsym : TObjSymbol;
  1501. bind : Tasmsymbind;
  1502. strname : string;
  1503. auxrec : array[0..17] of byte;
  1504. objsec : TObjSection;
  1505. begin
  1506. with TCoffObjData(objdata) do
  1507. begin
  1508. nsyms:=FCoffSyms.Size div sizeof(CoffSymbol);
  1509. { Allocate memory for symidx -> TObjSymbol table }
  1510. GetMem(FSymTbl,nsyms*sizeof(TObjSymbolrec));
  1511. FillChar(FSymTbl^,nsyms*sizeof(TObjSymbolrec),0);
  1512. { Load the Symbols }
  1513. FCoffSyms.Seek(0);
  1514. symidx:=0;
  1515. while (symidx<nsyms) do
  1516. begin
  1517. FCoffSyms.Read(sym,sizeof(sym));
  1518. if plongint(@sym.name)^<>0 then
  1519. begin
  1520. move(sym.name,strname[1],8);
  1521. strname[9]:=#0;
  1522. strname[0]:=chr(strlen(@strname[1]));
  1523. if strname='' then
  1524. Internalerror(200205171);
  1525. end
  1526. else
  1527. strname:=Read_str(sym.strpos);
  1528. bind:=AB_EXTERNAL;
  1529. size:=0;
  1530. address:=0;
  1531. objsym:=nil;
  1532. objsec:=nil;
  1533. case sym.typ of
  1534. COFF_SYM_GLOBAL :
  1535. begin
  1536. if sym.section=0 then
  1537. begin
  1538. if sym.value=0 then
  1539. bind:=AB_EXTERNAL
  1540. else
  1541. begin
  1542. bind:=AB_COMMON;
  1543. size:=sym.value;
  1544. end;
  1545. end
  1546. else
  1547. begin
  1548. bind:=AB_GLOBAL;
  1549. objsec:=GetSection(sym.section);
  1550. if sym.value>=objsec.mempos then
  1551. address:=sym.value-objsec.mempos;
  1552. end;
  1553. objsym:=CreateSymbol(strname);
  1554. objsym.bind:=bind;
  1555. objsym.typ:=AT_FUNCTION;
  1556. objsym.objsection:=objsec;
  1557. objsym.offset:=address;
  1558. objsym.size:=size;
  1559. { Register in ObjSection }
  1560. if assigned(objsec) then
  1561. objsec.AddSymbolDefine(objsym);
  1562. end;
  1563. COFF_SYM_LABEL,
  1564. COFF_SYM_LOCAL :
  1565. begin
  1566. { do not add constants (section=-1) }
  1567. if sym.section<>-1 then
  1568. begin
  1569. bind:=AB_LOCAL;
  1570. objsec:=GetSection(sym.section);
  1571. if sym.value>=objsec.mempos then
  1572. address:=sym.value-objsec.mempos;
  1573. objsym:=CreateSymbol(strname);
  1574. objsym.bind:=bind;
  1575. objsym.typ:=AT_FUNCTION;
  1576. objsym.objsection:=objsec;
  1577. objsym.offset:=address;
  1578. objsym.size:=size;
  1579. end;
  1580. end;
  1581. COFF_SYM_SECTION :
  1582. begin
  1583. if sym.section=0 then
  1584. InputError('Failed reading coff file, illegal section');
  1585. objsec:=GetSection(sym.section);
  1586. if assigned(objsec) then
  1587. begin
  1588. if sym.value>=objsec.mempos then
  1589. address:=sym.value-objsec.mempos;
  1590. objsym:=CreateSymbol(strname);
  1591. objsym.bind:=AB_LOCAL;
  1592. objsym.typ:=AT_FUNCTION;
  1593. objsym.objsection:=objsec;
  1594. objsym.offset:=address;
  1595. objsym.size:=size;
  1596. end;
  1597. end;
  1598. COFF_SYM_FUNCTION,
  1599. COFF_SYM_FILE :
  1600. ;
  1601. else
  1602. internalerror(200602232);
  1603. end;
  1604. FSymTbl^[symidx].sym:=objsym;
  1605. FSymTbl^[symidx].orgsize:=size;
  1606. { read aux records }
  1607. for i:=1 to sym.aux do
  1608. begin
  1609. FCoffSyms.Read(auxrec,sizeof(auxrec));
  1610. inc(symidx);
  1611. end;
  1612. inc(symidx);
  1613. end;
  1614. end;
  1615. end;
  1616. procedure TCoffObjInput.ObjSections_read_data(p:TObject;arg:pointer);
  1617. begin
  1618. with TCoffObjSection(p) do
  1619. begin
  1620. { Skip debug sections }
  1621. if (oso_debug in secoptions) and
  1622. (cs_link_strip in current_settings.globalswitches) and
  1623. not(cs_link_separate_dbg_file in current_settings.globalswitches) then
  1624. exit;
  1625. if assigned(data) then
  1626. begin
  1627. FReader.Seek(datapos);
  1628. if not FReader.ReadArray(data,Size) then
  1629. begin
  1630. Comment(V_Error,'Error reading coff file, can''t read object data');
  1631. exit;
  1632. end;
  1633. end;
  1634. end;
  1635. end;
  1636. procedure TCoffObjInput.ObjSections_read_relocs(p:TObject;arg:pointer);
  1637. begin
  1638. with TCoffObjSection(p) do
  1639. begin
  1640. { Skip debug sections }
  1641. if (oso_debug in secoptions) and
  1642. (cs_link_strip in current_settings.globalswitches) and
  1643. not(cs_link_separate_dbg_file in current_settings.globalswitches) then
  1644. exit;
  1645. if coffrelocs>0 then
  1646. begin
  1647. FReader.Seek(coffrelocpos);
  1648. read_relocs(TCoffObjSection(p));
  1649. end;
  1650. end;
  1651. end;
  1652. function TCoffObjInput.ReadObjData(AReader:TObjectreader;objdata:TObjData):boolean;
  1653. var
  1654. secalign : shortint;
  1655. strsize,
  1656. strpos,
  1657. i : longint;
  1658. code : longint;
  1659. objsec : TCoffObjSection;
  1660. secoptions : TObjSectionOptions;
  1661. header : tcoffheader;
  1662. sechdr : tcoffsechdr;
  1663. secname : string;
  1664. secnamebuf : array[0..15] of char;
  1665. begin
  1666. FReader:=AReader;
  1667. InputFileName:=AReader.FileName;
  1668. result:=false;
  1669. FCoffSyms:=TDynamicArray.Create(SymbolMaxGrow);
  1670. FCoffStrs:=TDynamicArray.Create(StrsMaxGrow);
  1671. with TCoffObjData(objdata) do
  1672. begin
  1673. { Read COFF header }
  1674. if not AReader.read(header,sizeof(tcoffheader)) then
  1675. begin
  1676. InputError('Can''t read COFF Header');
  1677. exit;
  1678. end;
  1679. if header.mach<>COFF_MAGIC then
  1680. begin
  1681. InputError('Illegal COFF Magic');
  1682. exit;
  1683. end;
  1684. {$ifdef arm}
  1685. eVCobj:=header.flag=$100;
  1686. {$endif arm}
  1687. { Strings }
  1688. AReader.Seek(header.sympos+header.syms*sizeof(CoffSymbol));
  1689. if not AReader.Read(strsize,4) then
  1690. begin
  1691. InputError('Error reading COFF Symtable');
  1692. exit;
  1693. end;
  1694. if (strsize>4) and not AReader.ReadArray(FCoffStrs,Strsize-4) then
  1695. begin
  1696. InputError('Error reading COFF Symtable');
  1697. exit;
  1698. end;
  1699. { Section headers }
  1700. { Allocate SecIdx -> TObjSection table, secidx is 1-based }
  1701. FSecCount:=header.nsects;
  1702. GetMem(FSecTbl,(header.nsects+1)*sizeof(TObjSection));
  1703. FillChar(FSecTbl^,(header.nsects+1)*sizeof(TObjSection),0);
  1704. AReader.Seek(sizeof(tcoffheader)+header.opthdr);
  1705. for i:=1 to header.nsects do
  1706. begin
  1707. if not AReader.read(sechdr,sizeof(sechdr)) then
  1708. begin
  1709. InputError('Error reading COFF Section Headers');
  1710. exit;
  1711. end;
  1712. move(sechdr.name,secnamebuf,8);
  1713. secnamebuf[8]:=#0;
  1714. secname:=strpas(secnamebuf);
  1715. if secname[1]='/' then
  1716. begin
  1717. Val(Copy(secname,2,8),strpos,code);
  1718. if code=0 then
  1719. secname:=Read_str(strpos)
  1720. else
  1721. begin
  1722. InputError('Error reading COFF Section Headers');
  1723. secname:='error';
  1724. end;
  1725. end;
  1726. if win32 then
  1727. pedecodesechdrflags(secname,sechdr.flags,secoptions,secalign)
  1728. else
  1729. begin
  1730. djdecodesechdrflags(secname,sechdr.flags);
  1731. secalign:=sizeof(pint);
  1732. end;
  1733. if (Length(secname)>3) and (secname[2] in ['e','f','i','p','r']) then
  1734. begin
  1735. if (Copy(secname,1,6)='.edata') or
  1736. (Copy(secname,1,5)='.rsrc') or
  1737. (Copy(secname,1,6)='.pdata') or
  1738. (Copy(secname,1,4)='.fpc') then
  1739. include(secoptions,oso_keep);
  1740. if (Copy(secname,1,6)='.idata') then
  1741. begin
  1742. { TODO: idata keep can maybe replaced with grouping of text and idata}
  1743. include(secoptions,oso_keep);
  1744. secname:=secname + '.' + ExtractFileName(InputFileName);
  1745. end;
  1746. end;
  1747. objsec:=TCoffObjSection(createsection(secname,secalign,secoptions,false));
  1748. FSecTbl^[i]:=objsec;
  1749. if not win32 then
  1750. objsec.mempos:=sechdr.rvaofs;
  1751. objsec.orgmempos:=sechdr.rvaofs;
  1752. objsec.coffrelocs:=sechdr.nrelocs;
  1753. objsec.coffrelocpos:=sechdr.relocpos;
  1754. objsec.datapos:=sechdr.datapos;
  1755. objsec.Size:=sechdr.dataSize;
  1756. end;
  1757. { ObjSymbols }
  1758. AReader.Seek(header.sympos);
  1759. if not AReader.ReadArray(FCoffSyms,header.syms*sizeof(CoffSymbol)) then
  1760. begin
  1761. Comment(V_Error,'Error reading coff file');
  1762. exit;
  1763. end;
  1764. { Insert all ObjSymbols }
  1765. read_symbols(objdata);
  1766. { Section Data }
  1767. ObjSectionList.ForEachCall(@objsections_read_data,nil);
  1768. { Relocs }
  1769. ObjSectionList.ForEachCall(@objsections_read_relocs,nil);
  1770. end;
  1771. FCoffStrs.Free;
  1772. FCoffStrs:=nil;
  1773. FCoffSyms.Free;
  1774. FCoffSyms:=nil;
  1775. result:=true;
  1776. end;
  1777. constructor TDJCoffObjInput.create;
  1778. begin
  1779. inherited createcoff(false);
  1780. cobjdata:=TDJCoffObjData;
  1781. end;
  1782. constructor TPECoffObjInput.create;
  1783. begin
  1784. inherited createcoff(true);
  1785. cobjdata:=TPECoffObjData;
  1786. end;
  1787. {****************************************************************************
  1788. TCoffexesection
  1789. ****************************************************************************}
  1790. constructor TCoffExeSection.createcoff(AList:TFPHashObjectList;const n:string;awin32:boolean);
  1791. begin
  1792. inherited create(AList,n);
  1793. win32:=awin32;
  1794. end;
  1795. constructor TDJCoffExeSection.create(AList:TFPHashObjectList;const n:string);
  1796. begin
  1797. inherited createcoff(AList,n,false);
  1798. end;
  1799. constructor TPECoffExeSection.create(AList:TFPHashObjectList;const n:string);
  1800. begin
  1801. inherited createcoff(AList,n,false);
  1802. end;
  1803. {****************************************************************************
  1804. TCoffexeoutput
  1805. ****************************************************************************}
  1806. constructor TCoffexeoutput.createcoff(awin32:boolean);
  1807. begin
  1808. inherited create;
  1809. win32:=awin32;
  1810. if target_info.system in [system_x86_64_win64] then
  1811. MaxMemPos:=$FFFFFFFF
  1812. else
  1813. if target_info.system in system_wince then
  1814. MaxMemPos:=$1FFFFFF
  1815. else
  1816. MaxMemPos:=$7FFFFFFF;
  1817. end;
  1818. procedure TCoffexeoutput.write_symbol(const name:string;value:aword;section:smallint;typ,aux:byte);
  1819. var
  1820. sym : coffsymbol;
  1821. begin
  1822. FillChar(sym,sizeof(sym),0);
  1823. if length(name)>8 then
  1824. begin
  1825. sym.strpos:=FCoffStrs.size+4;
  1826. FCoffStrs.writestr(name);
  1827. FCoffStrs.writestr(#0);
  1828. end
  1829. else
  1830. move(name[1],sym.name,length(name));
  1831. sym.value:=value;
  1832. sym.section:=section;
  1833. sym.typ:=typ;
  1834. sym.aux:=aux;
  1835. FWriter.write(sym,sizeof(sym));
  1836. end;
  1837. procedure TCoffexeoutput.globalsyms_write_symbol(p:TObject;arg:pointer);
  1838. var
  1839. secval,
  1840. value : aint;
  1841. globalval : byte;
  1842. exesec : TExeSection;
  1843. begin
  1844. if not assigned(texesymbol(p).objsymbol) then
  1845. internalerror(200603053);
  1846. with texesymbol(p).objsymbol do
  1847. begin
  1848. exesec:=TExeSection(objsection.exesection);
  1849. { There is no exesection defined for special internal symbols
  1850. like __image_base__ }
  1851. if assigned(exesec) then
  1852. begin
  1853. secval:=exesec.secsymidx;
  1854. value:=address-exesec.mempos;
  1855. end
  1856. else
  1857. begin
  1858. secval:=-1;
  1859. value:=address;
  1860. end;
  1861. if bind=AB_LOCAL then
  1862. globalval:=3
  1863. else
  1864. globalval:=2;
  1865. { reloctype address to the section in the executable }
  1866. write_symbol(name,value,secval,globalval,0);
  1867. end;
  1868. end;
  1869. procedure TCoffexeoutput.ExeSectionList_write_header(p:TObject;arg:pointer);
  1870. var
  1871. sechdr : tcoffsechdr;
  1872. s : string;
  1873. strpos : aword;
  1874. begin
  1875. with tExeSection(p) do
  1876. begin
  1877. fillchar(sechdr,sizeof(sechdr),0);
  1878. s:=name;
  1879. if length(s)>8 then
  1880. begin
  1881. strpos:=FCoffStrs.size+4;
  1882. FCoffStrs.writestr(s);
  1883. FCoffStrs.writestr(#0);
  1884. s:='/'+ToStr(strpos);
  1885. end;
  1886. move(s[1],sechdr.name,length(s));
  1887. sechdr.rvaofs:=mempos;
  1888. if win32 then
  1889. sechdr.vsize:=Size
  1890. else
  1891. sechdr.vsize:=mempos;
  1892. { sechdr.dataSize is size of initilized data. For .bss section it must be zero }
  1893. if (Name <> '.bss') then
  1894. sechdr.dataSize:=Size;
  1895. if (sechdr.dataSize>0) and
  1896. (oso_data in SecOptions) then
  1897. sechdr.datapos:=datapos;
  1898. sechdr.nrelocs:=0;
  1899. sechdr.relocpos:=0;
  1900. if win32 then
  1901. sechdr.flags:=peencodesechdrflags(SecOptions,SecAlign)
  1902. else
  1903. sechdr.flags:=djencodesechdrflags(SecOptions);
  1904. FWriter.write(sechdr,sizeof(sechdr));
  1905. end;
  1906. end;
  1907. procedure TCoffexeoutput.ExeSectionList_pass2_header(p:TObject;arg:pointer);
  1908. begin
  1909. with TExeSection(p) do
  1910. begin
  1911. { The debuginfo sections should already be stripped }
  1912. { if (ExeWriteMode=ewm_exeonly) and
  1913. (oso_debug in SecOptions) then
  1914. internalerror(200801161); }
  1915. inc(plongint(arg)^);
  1916. secsymidx:=plongint(arg)^;
  1917. end;
  1918. end;
  1919. procedure Tcoffexeoutput.ExeSectionList_write_Data(p:TObject;arg:pointer);
  1920. var
  1921. objsec : TObjSection;
  1922. i : longint;
  1923. begin
  1924. with texesection(p) do
  1925. begin
  1926. { don't write normal section if writing only debug info }
  1927. if (ExeWriteMode=ewm_dbgonly) and
  1928. not(oso_debug in SecOptions) then
  1929. exit;
  1930. if oso_data in secoptions then
  1931. begin
  1932. FWriter.Writezeros(Align(FWriter.Size,SectionDataAlign)-FWriter.Size);
  1933. for i:=0 to ObjSectionList.Count-1 do
  1934. begin
  1935. objsec:=TObjSection(ObjSectionList[i]);
  1936. if oso_data in objsec.secoptions then
  1937. begin
  1938. if not assigned(objsec.data) then
  1939. internalerror(200603042);
  1940. FWriter.writezeros(objsec.dataalignbytes);
  1941. if objsec.DataPos<>FWriter.Size then
  1942. internalerror(200602251);
  1943. FWriter.writearray(objsec.data);
  1944. end;
  1945. end;
  1946. end;
  1947. end;
  1948. end;
  1949. function tcoffexeoutput.totalheadersize:longword;
  1950. var
  1951. stubsize,
  1952. optheadersize : longword;
  1953. begin
  1954. if win32 then
  1955. begin
  1956. stubsize:=sizeof(win32stub)+sizeof(pemagic);
  1957. optheadersize:=sizeof(tcoffpeoptheader);
  1958. end
  1959. else
  1960. begin
  1961. stubsize:=sizeof(go32v2stub);
  1962. optheadersize:=sizeof(coffdjoptheader);
  1963. end;
  1964. result:=stubsize+sizeof(tcoffheader)+optheadersize;
  1965. end;
  1966. procedure tcoffexeoutput.MemPos_Header;
  1967. begin
  1968. { calculate start positions after the headers }
  1969. currmempos:=totalheadersize+sizeof(tcoffsechdr)*longword(ExeSectionList.Count-2);
  1970. end;
  1971. procedure tcoffexeoutput.DataPos_Header;
  1972. begin
  1973. { retrieve amount of sections }
  1974. nsects:=0;
  1975. ExeSectionList.ForEachCall(@ExeSectionList_pass2_header,@nsects);
  1976. { calculate start positions after the headers }
  1977. currdatapos:=totalheadersize+longword(nsects)*sizeof(tcoffsechdr);
  1978. end;
  1979. procedure tcoffexeoutput.DataPos_Symbols;
  1980. begin
  1981. inherited DataPos_Symbols;
  1982. { Calculating symbols position and size }
  1983. nsyms:=ExeSymbolList.Count;
  1984. sympos:=CurrDataPos;
  1985. inc(CurrDataPos,sizeof(coffsymbol)*nsyms);
  1986. end;
  1987. function TCoffexeoutput.writedata:boolean;
  1988. var
  1989. i : longword;
  1990. header : tcoffheader;
  1991. djoptheader : coffdjoptheader;
  1992. peoptheader : tcoffpeoptheader;
  1993. textExeSec,
  1994. dataExeSec,
  1995. bssExeSec,
  1996. idataExeSec : TExeSection;
  1997. hassymbols,
  1998. writeDbgStrings : boolean;
  1999. procedure UpdateDataDir(const secname:string;idx:longint);
  2000. var
  2001. exesec : TExeSection;
  2002. begin
  2003. exesec:=FindExeSection(secname);
  2004. if assigned(exesec) then
  2005. begin
  2006. peoptheader.DataDirectory[idx].vaddr:=exesec.mempos;
  2007. peoptheader.DataDirectory[idx].size:=exesec.Size;
  2008. end;
  2009. end;
  2010. begin
  2011. result:=false;
  2012. FCoffSyms:=TDynamicArray.Create(SymbolMaxGrow);
  2013. FCoffStrs:=TDynamicArray.Create(StrsMaxGrow);
  2014. textExeSec:=FindExeSection('.text');
  2015. dataExeSec:=FindExeSection('.data');
  2016. bssExeSec:=FindExeSection('.bss');
  2017. if not assigned(TextExeSec) or
  2018. not assigned(DataExeSec) then
  2019. internalerror(200602231);
  2020. { do we need to write symbols? }
  2021. hassymbols:=(ExeWriteMode=ewm_dbgonly) or
  2022. (
  2023. (ExeWriteMode=ewm_exefull) and
  2024. not(cs_link_strip in current_settings.globalswitches)
  2025. );
  2026. writeDbgStrings:=hassymbols or ((ExeWriteMode=ewm_exeonly) and (cs_link_separate_dbg_file in current_settings.globalswitches));
  2027. { Stub }
  2028. if win32 then
  2029. begin
  2030. FWriter.write(win32stub,sizeof(win32stub));
  2031. FWriter.write(pemagic,sizeof(pemagic));
  2032. end
  2033. else
  2034. FWriter.write(go32v2stub,sizeof(go32v2stub));
  2035. { Initial header, will be updated later }
  2036. fillchar(header,sizeof(header),0);
  2037. header.mach:=COFF_MAGIC;
  2038. header.nsects:=nsects;
  2039. if writeDbgStrings then
  2040. header.sympos:=sympos;
  2041. if hassymbols then
  2042. header.syms:=nsyms;
  2043. if win32 then
  2044. header.opthdr:=sizeof(tcoffpeoptheader)
  2045. else
  2046. header.opthdr:=sizeof(coffdjoptheader);
  2047. if win32 then
  2048. begin
  2049. header.flag:=PE_FILE_EXECUTABLE_IMAGE or PE_FILE_LINE_NUMS_STRIPPED;
  2050. if target_info.system in [system_x86_64_win64] then
  2051. header.flag:=header.flag or PE_FILE_LARGE_ADDRESS_AWARE
  2052. else
  2053. header.flag:=header.flag or PE_FILE_32BIT_MACHINE;
  2054. if IsSharedLibrary then
  2055. header.flag:=header.flag or PE_FILE_DLL;
  2056. if FindExeSection('.reloc')=nil then
  2057. header.flag:=header.flag or PE_FILE_RELOCS_STRIPPED;
  2058. if (FindExeSection('.stab')=nil) and
  2059. (FindExeSection('.debug_info')=nil) and
  2060. (FindExeSection('.gnu_debuglink')=nil) then
  2061. header.flag:=header.flag or PE_FILE_DEBUG_STRIPPED;
  2062. if not hassymbols then
  2063. header.flag:=header.flag or PE_FILE_LOCAL_SYMS_STRIPPED;
  2064. if SetPEFlagsSetExplicity then
  2065. header.flag:=header.flag or peflags;
  2066. end
  2067. else
  2068. header.flag:=COFF_FLAG_AR32WR or COFF_FLAG_EXE or COFF_FLAG_NORELOCS or COFF_FLAG_NOLINES;
  2069. FWriter.write(header,sizeof(header));
  2070. { Optional COFF Header }
  2071. if win32 then
  2072. begin
  2073. fillchar(peoptheader,sizeof(peoptheader),0);
  2074. peoptheader.magic:=COFF_OPT_MAGIC;
  2075. peoptheader.MajorLinkerVersion:=ord(version_nr)-ord('0');
  2076. peoptheader.MinorLinkerVersion:=(ord(release_nr)-ord('0'))*10 + (ord(patch_nr)-ord('0'));
  2077. peoptheader.tsize:=TextExeSec.Size;
  2078. peoptheader.dsize:=DataExeSec.Size;
  2079. if assigned(BSSExeSec) then
  2080. peoptheader.bsize:=BSSExeSec.Size;
  2081. peoptheader.text_start:=TextExeSec.mempos;
  2082. {$ifndef x86_64}
  2083. peoptheader.data_start:=DataExeSec.mempos;
  2084. {$endif x86_64}
  2085. peoptheader.entry:=EntrySym.Address;
  2086. peoptheader.ImageBase:=ImageBase;
  2087. peoptheader.SectionAlignment:=SectionMemAlign;
  2088. peoptheader.FileAlignment:=SectionDataAlign;
  2089. peoptheader.MajorOperatingSystemVersion:=4;
  2090. peoptheader.MinorOperatingSystemVersion:=0;
  2091. peoptheader.MajorImageVersion:=dllmajor;
  2092. peoptheader.MinorImageVersion:=dllminor;
  2093. if target_info.system in system_wince then
  2094. peoptheader.MajorSubsystemVersion:=3
  2095. else
  2096. peoptheader.MajorSubsystemVersion:=4;
  2097. peoptheader.MinorSubsystemVersion:=0;
  2098. peoptheader.Win32Version:=0;
  2099. peoptheader.SizeOfImage:=Align(CurrMemPos,SectionMemAlign);
  2100. peoptheader.SizeOfHeaders:=textExeSec.DataPos;
  2101. peoptheader.CheckSum:=0;
  2102. if target_info.system in system_wince then
  2103. peoptheader.Subsystem:=PE_SUBSYSTEM_WINDOWS_CE_GUI
  2104. else
  2105. if apptype=app_gui then
  2106. peoptheader.Subsystem:=PE_SUBSYSTEM_WINDOWS_GUI
  2107. else
  2108. peoptheader.Subsystem:=PE_SUBSYSTEM_WINDOWS_CUI;
  2109. peoptheader.DllCharacteristics:=0;
  2110. peoptheader.SizeOfStackReserve:=stacksize;
  2111. peoptheader.SizeOfStackCommit:=$1000;
  2112. if MinStackSizeSetExplicity then
  2113. peoptheader.SizeOfStackCommit:=minstacksize;
  2114. if MaxStackSizeSetExplicity then
  2115. peoptheader.SizeOfStackReserve:=maxstacksize;
  2116. peoptheader.SizeOfHeapReserve:=$100000;
  2117. peoptheader.SizeOfHeapCommit:=$1000;
  2118. peoptheader.NumberOfRvaAndSizes:=PE_DATADIR_ENTRIES;
  2119. UpdateDataDir('.idata',PE_DATADIR_IDATA);
  2120. UpdateDataDir('.edata',PE_DATADIR_EDATA);
  2121. UpdateDataDir('.rsrc',PE_DATADIR_RSRC);
  2122. UpdateDataDir('.pdata',PE_DATADIR_PDATA);
  2123. UpdateDataDir('.reloc',PE_DATADIR_RELOC);
  2124. FWriter.write(peoptheader,sizeof(peoptheader));
  2125. end
  2126. else
  2127. begin
  2128. fillchar(djoptheader,sizeof(djoptheader),0);
  2129. djoptheader.magic:=COFF_OPT_MAGIC;
  2130. djoptheader.tsize:=TextExeSec.Size;
  2131. djoptheader.dsize:=DataExeSec.Size;
  2132. if assigned(BSSExeSec) then
  2133. djoptheader.bsize:=BSSExeSec.Size;
  2134. djoptheader.text_start:=TextExeSec.mempos;
  2135. djoptheader.data_start:=DataExeSec.mempos;
  2136. djoptheader.entry:=EntrySym.offset;
  2137. FWriter.write(djoptheader,sizeof(djoptheader));
  2138. end;
  2139. { For some unknown reason WM 6.1 requires .idata section to be read only.
  2140. Otherwise it refuses to load DLLs greater than 64KB.
  2141. Earlier versions of WinCE load DLLs regardless of .idata flags. }
  2142. if target_info.system in system_wince then
  2143. begin
  2144. idataExeSec:=FindExeSection('.idata');
  2145. if idataExeSec<>nil then
  2146. idataExeSec.SecOptions:=idataExeSec.SecOptions - [oso_write] + [oso_readonly];
  2147. end;
  2148. { Section headers }
  2149. ExeSectionList.ForEachCall(@ExeSectionList_write_header,nil);
  2150. { Section data }
  2151. ExeSectionList.ForEachCall(@ExeSectionList_write_data,nil);
  2152. { Optional Symbols }
  2153. if SymPos<>FWriter.Size then
  2154. internalerror(200602252);
  2155. if hassymbols then
  2156. ExeSymbolList.ForEachCall(@globalsyms_write_symbol,nil);
  2157. if writeDbgStrings then
  2158. begin
  2159. { Strings }
  2160. i:=FCoffStrs.size+4;
  2161. FWriter.write(i,4);
  2162. FWriter.writearray(FCoffStrs);
  2163. end;
  2164. { Release }
  2165. FCoffStrs.Free;
  2166. FCoffSyms.Free;
  2167. result:=true;
  2168. end;
  2169. function IdataObjSectionCompare(Item1, Item2: Pointer): Integer;
  2170. var
  2171. I1 : TObjSection absolute Item1;
  2172. I2 : TObjSection absolute Item2;
  2173. begin
  2174. Result:=CompareStr(I1.Name,I2.Name);
  2175. end;
  2176. procedure TCoffexeoutput.Order_ObjSectionList(ObjSectionList: TFPObjectList);
  2177. begin
  2178. if CurrExeSec.Name = '.idata' then
  2179. ObjSectionList.Sort(@IdataObjSectionCompare);
  2180. end;
  2181. constructor TDJCoffexeoutput.create;
  2182. begin
  2183. inherited createcoff(false);
  2184. CExeSection:=TDJCoffExeSection;
  2185. CObjData:=TPECoffObjData;
  2186. end;
  2187. constructor TPECoffexeoutput.create;
  2188. begin
  2189. inherited createcoff(true);
  2190. CExeSection:=TPECoffExeSection;
  2191. CObjData:=TPECoffObjData;
  2192. end;
  2193. procedure TPECoffexeoutput.GenerateLibraryImports(ImportLibraryList:TFPHashObjectList);
  2194. var
  2195. textobjsection,
  2196. idata2objsection,
  2197. idata4objsection,
  2198. idata5objsection,
  2199. idata6objsection,
  2200. idata7objsection : TObjSection;
  2201. idata2label : TObjSymbol;
  2202. basedllname : string;
  2203. procedure StartImport(const dllname:string);
  2204. var
  2205. idata4label,
  2206. idata5label,
  2207. idata7label : TObjSymbol;
  2208. emptyint : longint;
  2209. begin
  2210. if assigned(exemap) then
  2211. begin
  2212. exemap.Add('');
  2213. exemap.Add('Importing from DLL '+dllname);
  2214. end;
  2215. emptyint:=0;
  2216. basedllname:=ExtractFileName(dllname);
  2217. idata2objsection:=internalobjdata.createsection(sec_idata2,basedllname);
  2218. idata2label:=internalobjdata.SymbolDefine('__imp_dir_'+basedllname,AB_LOCAL,AT_DATA);
  2219. idata4objsection:=internalobjdata.createsection(sec_idata4,basedllname);
  2220. idata4label:=internalobjdata.SymbolDefine('__imp_names_'+basedllname,AB_LOCAL,AT_DATA);
  2221. idata5objsection:=internalobjdata.createsection(sec_idata5,basedllname);
  2222. idata5label:=internalobjdata.SymbolDefine('__imp_fixup_'+basedllname,AB_LOCAL,AT_DATA);
  2223. idata7objsection:=internalobjdata.createsection(sec_idata7,basedllname);
  2224. idata7label:=internalobjdata.SymbolDefine('__imp_dll_'+basedllname,AB_LOCAL,AT_DATA);
  2225. { idata2 }
  2226. internalobjdata.SetSection(idata2objsection);
  2227. { dummy links to imports finalization }
  2228. internalobjdata.writereloc(0,0,internalobjdata.SymbolRef('__imp_names_end_'+basedllname),RELOC_NONE);
  2229. internalobjdata.writereloc(0,0,internalobjdata.SymbolRef('__imp_fixup_end_'+basedllname),RELOC_NONE);
  2230. { section data }
  2231. internalobjdata.writereloc(0,sizeof(longint),idata4label,RELOC_RVA);
  2232. internalobjdata.writebytes(emptyint,sizeof(emptyint));
  2233. internalobjdata.writebytes(emptyint,sizeof(emptyint));
  2234. internalobjdata.writereloc(0,sizeof(longint),idata7label,RELOC_RVA);
  2235. internalobjdata.writereloc(0,sizeof(longint),idata5label,RELOC_RVA);
  2236. { idata7 }
  2237. internalobjdata.SetSection(idata7objsection);
  2238. internalobjdata.writebytes(basedllname[1],length(basedllname));
  2239. internalobjdata.writebytes(emptyint,1);
  2240. end;
  2241. procedure EndImport;
  2242. var
  2243. emptyint : longint;
  2244. begin
  2245. emptyint:=0;
  2246. idata4objsection:=internalobjdata.createsection(sec_idata4, basedllname+'_z_');
  2247. internalobjdata.SymbolDefine('__imp_names_end_'+basedllname,AB_LOCAL,AT_DATA);
  2248. idata5objsection:=internalobjdata.createsection(sec_idata5, basedllname+'_z_');
  2249. internalobjdata.SymbolDefine('__imp_fixup_end_'+basedllname,AB_LOCAL,AT_DATA);
  2250. { idata4 }
  2251. internalobjdata.SetSection(idata4objsection);
  2252. internalobjdata.writebytes(emptyint,sizeof(emptyint));
  2253. if target_info.system=system_x86_64_win64 then
  2254. internalobjdata.writebytes(emptyint,sizeof(emptyint));
  2255. { idata5 }
  2256. internalobjdata.SetSection(idata5objsection);
  2257. internalobjdata.writebytes(emptyint,sizeof(emptyint));
  2258. if target_info.system=system_x86_64_win64 then
  2259. internalobjdata.writebytes(emptyint,sizeof(emptyint));
  2260. { be sure that this will not be removed }
  2261. idata4objsection.SecOptions:=idata4objsection.SecOptions + [oso_keep];
  2262. idata5objsection.SecOptions:=idata5objsection.SecOptions + [oso_keep];
  2263. end;
  2264. function AddImport(const afuncname,amangledname:string; AOrdNr:longint;isvar:boolean):TObjSymbol;
  2265. const
  2266. {$ifdef x86_64}
  2267. jmpopcode : array[0..1] of byte = (
  2268. $ff,$25 // jmp qword [rip + offset32]
  2269. );
  2270. {$else x86_64}
  2271. {$ifdef arm}
  2272. jmpopcode : array[0..7] of byte = (
  2273. $00,$c0,$9f,$e5, // ldr ip, [pc, #0]
  2274. $00,$f0,$9c,$e5 // ldr pc, [ip]
  2275. );
  2276. {$else arm}
  2277. jmpopcode : array[0..1] of byte = (
  2278. $ff,$25
  2279. );
  2280. {$endif arm}
  2281. {$endif x86_64}
  2282. nopopcodes : array[0..1] of byte = (
  2283. $90,$90
  2284. );
  2285. var
  2286. idata4label,
  2287. idata5label,
  2288. idata6label : TObjSymbol;
  2289. emptyint : longint;
  2290. secname,
  2291. num : string;
  2292. absordnr: word;
  2293. procedure WriteTableEntry;
  2294. var
  2295. ordint: dword;
  2296. begin
  2297. if AOrdNr <= 0 then
  2298. begin
  2299. { import by name }
  2300. internalobjdata.writereloc(0,sizeof(longint),idata6label,RELOC_RVA);
  2301. if target_info.system=system_x86_64_win64 then
  2302. internalobjdata.writebytes(emptyint,sizeof(emptyint));
  2303. end
  2304. else
  2305. begin
  2306. { import by ordinal }
  2307. ordint:=AOrdNr;
  2308. if target_info.system=system_x86_64_win64 then
  2309. begin
  2310. internalobjdata.writebytes(ordint,sizeof(ordint));
  2311. ordint:=$80000000;
  2312. internalobjdata.writebytes(ordint,sizeof(ordint));
  2313. end
  2314. else
  2315. begin
  2316. ordint:=ordint or $80000000;
  2317. internalobjdata.writebytes(ordint,sizeof(ordint));
  2318. end;
  2319. end;
  2320. end;
  2321. begin
  2322. result:=nil;
  2323. emptyint:=0;
  2324. if assigned(exemap) then
  2325. begin
  2326. if AOrdNr <= 0 then
  2327. exemap.Add(' Importing Function '+afuncname)
  2328. else
  2329. exemap.Add(' Importing Function '+afuncname+' (OrdNr='+tostr(AOrdNr)+')');
  2330. end;
  2331. with internalobjdata do
  2332. begin
  2333. secname:=basedllname+'_i_'+amangledname;
  2334. textobjsection:=createsection(sectionname(sec_code,secname,secorder_default),current_settings.alignment.procalign,sectiontype2options(sec_code) - [oso_keep]);
  2335. idata4objsection:=createsection(sec_idata4, secname);
  2336. idata5objsection:=createsection(sec_idata5, secname);
  2337. idata6objsection:=createsection(sec_idata6, secname);
  2338. end;
  2339. { idata6, import data (ordnr+name) }
  2340. internalobjdata.SetSection(idata6objsection);
  2341. inc(idatalabnr);
  2342. num:=tostr(idatalabnr);
  2343. idata6label:=internalobjdata.SymbolDefine('__imp_'+num,AB_LOCAL,AT_DATA);
  2344. absordnr:=Abs(AOrdNr);
  2345. { write index hint }
  2346. internalobjdata.writebytes(absordnr,2);
  2347. if AOrdNr <= 0 then
  2348. internalobjdata.writebytes(afuncname[1],length(afuncname));
  2349. internalobjdata.writebytes(emptyint,1);
  2350. internalobjdata.writebytes(emptyint,align(internalobjdata.CurrObjSec.size,2)-internalobjdata.CurrObjSec.size);
  2351. { idata4, import lookup table }
  2352. internalobjdata.SetSection(idata4objsection);
  2353. idata4label:=internalobjdata.SymbolDefine('__imp_lookup_'+num,AB_LOCAL,AT_DATA);
  2354. WriteTableEntry;
  2355. { idata5, import address table }
  2356. internalobjdata.SetSection(idata5objsection);
  2357. { dummy back links }
  2358. internalobjdata.writereloc(0,0,idata4label,RELOC_NONE);
  2359. internalobjdata.writereloc(0,0,idata2label,RELOC_NONE);
  2360. { section data }
  2361. if isvar then
  2362. result:=internalobjdata.SymbolDefine(amangledname,AB_GLOBAL,AT_DATA)
  2363. else
  2364. idata5label:=internalobjdata.SymbolDefine('__imp_'+amangledname,AB_LOCAL,AT_DATA);
  2365. WriteTableEntry;
  2366. { text, jmp }
  2367. if not isvar then
  2368. begin
  2369. internalobjdata.SetSection(textobjsection);
  2370. result:=internalobjdata.SymbolDefine('_'+amangledname,AB_GLOBAL,AT_FUNCTION);
  2371. internalobjdata.writebytes(jmpopcode,sizeof(jmpopcode));
  2372. {$ifdef x86_64}
  2373. internalobjdata.writereloc(0,4,idata5label,RELOC_RELATIVE);
  2374. {$else}
  2375. internalobjdata.writereloc(0,4,idata5label,RELOC_ABSOLUTE32);
  2376. {$endif x86_64}
  2377. internalobjdata.writebytes(nopopcodes,align(internalobjdata.CurrObjSec.size,sizeof(nopopcodes))-internalobjdata.CurrObjSec.size);
  2378. end;
  2379. end;
  2380. var
  2381. i,j : longint;
  2382. ImportLibrary : TImportLibrary;
  2383. ImportSymbol : TImportSymbol;
  2384. exesym : TExeSymbol;
  2385. begin
  2386. for i:=0 to ImportLibraryList.Count-1 do
  2387. begin
  2388. ImportLibrary:=TImportLibrary(ImportLibraryList[i]);
  2389. idata2objsection:=nil;
  2390. idata4objsection:=nil;
  2391. idata5objsection:=nil;
  2392. idata6objsection:=nil;
  2393. idata7objsection:=nil;
  2394. for j:=0 to ImportLibrary.ImportSymbolList.Count-1 do
  2395. begin
  2396. ImportSymbol:=TImportSymbol(ImportLibrary.ImportSymbolList[j]);
  2397. exesym:=TExeSymbol(ExeSymbolList.Find(ImportSymbol.MangledName));
  2398. if assigned(exesym) and
  2399. (exesym.State<>symstate_defined) then
  2400. begin
  2401. if not assigned(idata2objsection) then
  2402. StartImport(ImportLibrary.Name);
  2403. exesym.objsymbol:=AddImport(ImportSymbol.Name,ImportSymbol.MangledName,ImportSymbol.OrdNr,ImportSymbol.IsVar);
  2404. exesym.State:=symstate_defined;
  2405. end;
  2406. end;
  2407. if assigned(idata2objsection) then
  2408. EndImport;
  2409. end;
  2410. PackUnresolvedExeSymbols('after DLL imports');
  2411. end;
  2412. procedure TPECoffexeoutput.GenerateRelocs;
  2413. var
  2414. pgaddr, hdrpos : longword;
  2415. procedure FinishBlock;
  2416. var
  2417. p,len : longint;
  2418. begin
  2419. if hdrpos = longword(-1) then
  2420. exit;
  2421. p:=0;
  2422. internalobjdata.writebytes(p,align(internalobjdata.CurrObjSec.size,4)-internalobjdata.CurrObjSec.size);
  2423. p:=internalObjData.CurrObjSec.Data.Pos;
  2424. internalObjData.CurrObjSec.Data.seek(hdrpos+4);
  2425. len:=p-hdrpos;
  2426. internalObjData.CurrObjSec.Data.write(len,4);
  2427. internalObjData.CurrObjSec.Data.seek(p);
  2428. hdrpos:=longword(-1);
  2429. end;
  2430. var
  2431. exesec : TExeSection;
  2432. objsec : TObjSection;
  2433. objreloc : TObjRelocation;
  2434. i,j,k : longint;
  2435. offset : longword;
  2436. w: word;
  2437. begin
  2438. if not RelocSection then
  2439. exit;
  2440. exesec:=FindExeSection('.reloc');
  2441. if exesec=nil then
  2442. exit;
  2443. objsec:=internalObjData.createsection('.reloc',0,exesec.SecOptions+[oso_data]);
  2444. exesec.AddObjSection(objsec);
  2445. pgaddr:=longword(-1);
  2446. hdrpos:=longword(-1);
  2447. for i:=0 to ExeSectionList.Count-1 do
  2448. begin
  2449. exesec:=TExeSection(ExeSectionList[i]);
  2450. for j:=0 to exesec.ObjSectionList.count-1 do
  2451. begin
  2452. objsec:=TObjSection(exesec.ObjSectionList[j]);
  2453. { create relocs only for sections which are loaded in memory }
  2454. if not (oso_load in objsec.SecOptions) then
  2455. continue;
  2456. for k:=0 to objsec.ObjRelocations.Count-1 do
  2457. begin
  2458. objreloc:=TObjRelocation(objsec.ObjRelocations[k]);
  2459. if not (objreloc.typ in [{$ifdef x86_64}RELOC_ABSOLUTE32,{$endif x86_64}RELOC_ABSOLUTE]) then
  2460. continue;
  2461. offset:=objsec.MemPos+objreloc.dataoffset;
  2462. if (offset<pgaddr) and (pgaddr<>longword(-1)) then
  2463. Internalerror(2007062701);
  2464. if (offset-pgaddr>=4096) or (pgaddr=longword(-1)) then
  2465. begin
  2466. FinishBlock;
  2467. pgaddr:=(offset div 4096)*4096;
  2468. hdrpos:=internalObjData.CurrObjSec.Data.Pos;
  2469. internalObjData.writebytes(pgaddr,4);
  2470. { Reserving space for block size. The size will be written later in FinishBlock }
  2471. internalObjData.writebytes(k,4);
  2472. end;
  2473. {$ifdef x86_64}
  2474. if objreloc.typ = RELOC_ABSOLUTE then
  2475. w:=IMAGE_REL_BASED_DIR64
  2476. else
  2477. {$endif x86_64}
  2478. w:=IMAGE_REL_BASED_HIGHLOW;
  2479. w:=(w shl 12) or (offset-pgaddr);
  2480. internalObjData.writebytes(w,2);
  2481. end;
  2482. end;
  2483. end;
  2484. FinishBlock;
  2485. end;
  2486. procedure TPECoffexeoutput.Order_End;
  2487. var
  2488. exesec : TExeSection;
  2489. begin
  2490. inherited;
  2491. if not IsSharedLibrary then
  2492. exit;
  2493. exesec:=FindExeSection('.reloc');
  2494. if exesec=nil then
  2495. exit;
  2496. exesec.SecOptions:=exesec.SecOptions + [oso_Data,oso_keep,oso_load];
  2497. end;
  2498. procedure TPECoffexeoutput.MemPos_ExeSection(const aname:string);
  2499. begin
  2500. if aname='.reloc' then
  2501. GenerateRelocs;
  2502. inherited;
  2503. end;
  2504. {****************************************************************************
  2505. TDJCoffAssembler
  2506. ****************************************************************************}
  2507. constructor TDJCoffAssembler.Create(smart:boolean);
  2508. begin
  2509. inherited Create(smart);
  2510. CObjOutput:=TDJCoffObjOutput;
  2511. end;
  2512. {****************************************************************************
  2513. TPECoffAssembler
  2514. ****************************************************************************}
  2515. constructor TPECoffAssembler.Create(smart:boolean);
  2516. begin
  2517. inherited Create(smart);
  2518. CObjOutput:=TPECoffObjOutput;
  2519. end;
  2520. {*****************************************************************************
  2521. DLLReader
  2522. *****************************************************************************}
  2523. {$ifdef win32}
  2524. var
  2525. Wow64DisableWow64FsRedirection : function (var OldValue : pointer) : boolean;stdcall;
  2526. Wow64RevertWow64FsRedirection : function (OldValue : pointer) : boolean;stdcall;
  2527. {$endif win32}
  2528. function ReadDLLImports(const dllname:string;readdllproc:Treaddllproc):boolean;
  2529. type
  2530. TPECoffExpDir=packed record
  2531. flag,
  2532. stamp : cardinal;
  2533. Major,
  2534. Minor : word;
  2535. Name,
  2536. Base,
  2537. NumFuncs,
  2538. NumNames,
  2539. AddrFuncs,
  2540. AddrNames,
  2541. AddrOrds : cardinal;
  2542. end;
  2543. var
  2544. DLLReader : TObjectReader;
  2545. DosHeader : array[0..$7f] of byte;
  2546. PEMagic : array[0..3] of byte;
  2547. Header : TCoffHeader;
  2548. peheader : tcoffpeoptheader;
  2549. NameOfs,
  2550. newheaderofs : longword;
  2551. FuncName : string;
  2552. expdir : TPECoffExpDir;
  2553. i : longint;
  2554. found : boolean;
  2555. sechdr : tCoffSecHdr;
  2556. {$ifdef win32}
  2557. p : pointer;
  2558. {$endif win32}
  2559. begin
  2560. result:=false;
  2561. {$ifdef win32}
  2562. if (target_info.system=system_x86_64_win64) and
  2563. assigned(Wow64DisableWow64FsRedirection) then
  2564. Wow64DisableWow64FsRedirection(p);
  2565. {$endif win32}
  2566. DLLReader:=TObjectReader.Create;
  2567. DLLReader.OpenFile(dllname);
  2568. {$ifdef win32}
  2569. if (target_info.system=system_x86_64_win64) and
  2570. assigned(Wow64RevertWow64FsRedirection) then
  2571. Wow64RevertWow64FsRedirection(p);
  2572. {$endif win32}
  2573. if not DLLReader.Read(DosHeader,sizeof(DosHeader)) or
  2574. (DosHeader[0]<>$4d) or (DosHeader[1]<>$5a) then
  2575. begin
  2576. Comment(V_Error,'Invalid DLL '+dllname+', Dos Header invalid');
  2577. exit;
  2578. end;
  2579. newheaderofs:=cardinal(DosHeader[$3c]) or (DosHeader[$3d] shl 8) or (DosHeader[$3e] shl 16) or (DosHeader[$3f] shl 24);
  2580. DLLReader.Seek(newheaderofs);
  2581. if not DLLReader.Read(PEMagic,sizeof(PEMagic)) or
  2582. (PEMagic[0]<>$50) or (PEMagic[1]<>$45) or (PEMagic[2]<>$00) or (PEMagic[3]<>$00) then
  2583. begin
  2584. Comment(V_Error,'Invalid DLL '+dllname+': invalid magic code');
  2585. exit;
  2586. end;
  2587. if not DLLReader.Read(Header,sizeof(TCoffHeader)) or
  2588. (Header.mach<>COFF_MAGIC) or
  2589. (Header.opthdr<>sizeof(tcoffpeoptheader)) then
  2590. begin
  2591. Comment(V_Error,'Invalid DLL '+dllname+', invalid header size');
  2592. exit;
  2593. end;
  2594. { Read optheader }
  2595. DLLreader.Read(peheader,sizeof(tcoffpeoptheader));
  2596. { Section headers }
  2597. found:=false;
  2598. for i:=1 to header.nsects do
  2599. begin
  2600. if not DLLreader.read(sechdr,sizeof(sechdr)) then
  2601. begin
  2602. Comment(V_Error,'Error reading coff file '+DLLName);
  2603. exit;
  2604. end;
  2605. if (sechdr.rvaofs<=peheader.DataDirectory[PE_DATADIR_EDATA].vaddr) and
  2606. (peheader.DataDirectory[PE_DATADIR_EDATA].vaddr<sechdr.rvaofs+sechdr.vsize) then
  2607. begin
  2608. found:=true;
  2609. break;
  2610. end;
  2611. end;
  2612. if not found then
  2613. begin
  2614. Comment(V_Warning,'DLL '+DLLName+' does not contain any exports');
  2615. exit;
  2616. end;
  2617. { Process edata }
  2618. DLLReader.Seek(sechdr.datapos+peheader.DataDirectory[PE_DATADIR_EDATA].vaddr-sechdr.rvaofs);
  2619. DLLReader.Read(expdir,sizeof(expdir));
  2620. for i:=0 to expdir.NumNames-1 do
  2621. begin
  2622. DLLReader.Seek(sechdr.datapos+expdir.AddrNames-sechdr.rvaofs+i*4);
  2623. DLLReader.Read(NameOfs,4);
  2624. Dec(NameOfs,sechdr.rvaofs);
  2625. if (NameOfs<0) or
  2626. (NameOfs>sechdr.vsize) then
  2627. begin
  2628. Comment(V_Error,'DLL does contains invalid exports');
  2629. break;
  2630. end;
  2631. { Read Function name from DLL, prepend _ and terminate with #0 }
  2632. DLLReader.Seek(sechdr.datapos+NameOfs);
  2633. DLLReader.Read((@FuncName[1])^,sizeof(FuncName)-3);
  2634. FuncName[sizeof(FuncName)-1]:=#0;
  2635. FuncName[0]:=chr(Strlen(@FuncName[1]));
  2636. readdllproc(DLLName,FuncName);
  2637. end;
  2638. DLLReader.Free;
  2639. end;
  2640. {*****************************************************************************
  2641. Initialize
  2642. *****************************************************************************}
  2643. {$ifdef i386}
  2644. const
  2645. as_i386_coff_info : tasminfo =
  2646. (
  2647. id : as_i386_coff;
  2648. idtxt : 'COFF';
  2649. asmbin : '';
  2650. asmcmd : '';
  2651. supported_targets : [system_i386_go32v2];
  2652. flags : [af_outputbinary];
  2653. labelprefix : '.L';
  2654. comment : '';
  2655. );
  2656. as_i386_pecoff_info : tasminfo =
  2657. (
  2658. id : as_i386_pecoff;
  2659. idtxt : 'PECOFF';
  2660. asmbin : '';
  2661. asmcmd : '';
  2662. supported_targets : [system_i386_win32];
  2663. flags : [af_outputbinary,af_smartlink_sections];
  2664. labelprefix : '.L';
  2665. comment : '';
  2666. );
  2667. as_i386_pecoffwdosx_info : tasminfo =
  2668. (
  2669. id : as_i386_pecoffwdosx;
  2670. idtxt : 'PEWDOSX';
  2671. asmbin : '';
  2672. asmcmd : '';
  2673. supported_targets : [system_i386_wdosx];
  2674. flags : [af_outputbinary];
  2675. labelprefix : '.L';
  2676. comment : '';
  2677. );
  2678. as_i386_pecoffwince_info : tasminfo =
  2679. (
  2680. id : as_i386_pecoffwince;
  2681. idtxt : 'PECOFFWINCE';
  2682. asmbin : '';
  2683. asmcmd : '';
  2684. supported_targets : [system_i386_wince];
  2685. flags : [af_outputbinary,af_smartlink_sections];
  2686. labelprefix : '.L';
  2687. comment : '';
  2688. );
  2689. {$endif i386}
  2690. {$ifdef x86_64}
  2691. const
  2692. as_x86_64_pecoff_info : tasminfo =
  2693. (
  2694. id : as_x86_64_pecoff;
  2695. idtxt : 'PECOFF';
  2696. asmbin : '';
  2697. asmcmd : '';
  2698. supported_targets : [system_x86_64_win64];
  2699. flags : [af_outputbinary,af_smartlink_sections];
  2700. labelprefix : '.L';
  2701. comment : '';
  2702. );
  2703. {$endif x86_64}
  2704. {$ifdef arm}
  2705. const
  2706. as_arm_pecoffwince_info : tasminfo =
  2707. (
  2708. id : as_arm_pecoffwince;
  2709. idtxt : 'PECOFFWINCE';
  2710. asmbin : '';
  2711. asmcmd : '';
  2712. supported_targets : [system_arm_wince];
  2713. flags : [af_outputbinary];
  2714. labelprefix : '.L';
  2715. comment : '';
  2716. );
  2717. {$endif arm}
  2718. {$ifdef win32}
  2719. procedure SetupProcVars;
  2720. var
  2721. hinstLib : THandle;
  2722. begin
  2723. Wow64DisableWow64FsRedirection:=nil;
  2724. Wow64RevertWow64FsRedirection:=nil;
  2725. hinstLib:=LoadLibrary('kernel32.dll');
  2726. if hinstLib<>0 then
  2727. begin
  2728. pointer(Wow64DisableWow64FsRedirection):=GetProcAddress(hinstLib,'Wow64DisableWow64FsRedirection');
  2729. pointer(Wow64RevertWow64FsRedirection):=GetProcAddress(hinstLib,'Wow64RevertWow64FsRedirection');
  2730. FreeLibrary(hinstLib);
  2731. end;
  2732. end;
  2733. {$endif win32}
  2734. initialization
  2735. {$ifdef i386}
  2736. RegisterAssembler(as_i386_coff_info,TDJCoffAssembler);
  2737. RegisterAssembler(as_i386_pecoff_info,TPECoffAssembler);
  2738. RegisterAssembler(as_i386_pecoffwdosx_info,TPECoffAssembler);
  2739. RegisterAssembler(as_i386_pecoffwince_info,TPECoffAssembler);
  2740. {$endif i386}
  2741. {$ifdef x86_64}
  2742. RegisterAssembler(as_x86_64_pecoff_info,TPECoffAssembler);
  2743. {$endif x86_64}
  2744. {$ifdef arm}
  2745. RegisterAssembler(as_arm_pecoffwince_info,TPECoffAssembler);
  2746. {$endif arm}
  2747. {$ifdef win32}
  2748. SetupProcVars;
  2749. {$endif win32}
  2750. end.