ogcoff.pas 105 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949
  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. procedure MemPos_Header;override;
  212. procedure DataPos_Header;override;
  213. procedure DataPos_Symbols;override;
  214. function writedata:boolean;override;
  215. procedure Order_ObjSectionList(ObjSectionList : TFPObjectList);override;
  216. public
  217. constructor createcoff(awin32:boolean);
  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. aalign:=sizeof(pint);
  685. if flags and PE_SCN_CNT_CODE<>0 then
  686. include(aoptions,oso_executable);
  687. if flags and PE_SCN_MEM_DISCARDABLE<>0 then
  688. include(aoptions,oso_debug);
  689. if flags and PE_SCN_CNT_UNINITIALIZED_DATA=0 then
  690. include(aoptions,oso_data);
  691. if (flags and PE_SCN_LNK_REMOVE<>0) or
  692. (flags and PE_SCN_MEM_DISCARDABLE<>0) then
  693. include(aoptions,oso_noload)
  694. else
  695. include(aoptions,oso_load);
  696. { read/write }
  697. if flags and PE_SCN_MEM_WRITE<>0 then
  698. include(aoptions,oso_write)
  699. else
  700. include(aoptions,oso_readonly);
  701. { alignment }
  702. alignflag:=flags and PE_SCN_ALIGN_MASK;
  703. if alignflag=PE_SCN_ALIGN_64BYTES then
  704. aalign:=64
  705. else if alignflag=PE_SCN_ALIGN_32BYTES then
  706. aalign:=32
  707. else if alignflag=PE_SCN_ALIGN_16BYTES then
  708. aalign:=16
  709. else if alignflag=PE_SCN_ALIGN_8BYTES then
  710. aalign:=8
  711. else if alignflag=PE_SCN_ALIGN_4BYTES then
  712. aalign:=4
  713. else if alignflag=PE_SCN_ALIGN_2BYTES then
  714. aalign:=2
  715. else if alignflag=PE_SCN_ALIGN_1BYTES then
  716. aalign:=1;
  717. end;
  718. {****************************************************************************
  719. TCoffObjSection
  720. ****************************************************************************}
  721. constructor TCoffObjSection.create(AList:TFPHashObjectList;const aname:string;aalign:shortint;aoptions:TObjSectionOptions);
  722. begin
  723. inherited create(AList,aname,aalign,aoptions);
  724. end;
  725. procedure TCoffObjSection.addsymsizereloc(ofs:aword;p:TObjSymbol;symsize:aword;reloctype:TObjRelocationType);
  726. begin
  727. ObjRelocations.Add(TObjRelocation.createsymbolsize(ofs,p,symsize,reloctype));
  728. end;
  729. procedure TCoffObjSection.fixuprelocs;
  730. var
  731. i,zero : longint;
  732. objreloc : TObjRelocation;
  733. address,
  734. relocval : aint;
  735. relocsec : TObjSection;
  736. begin
  737. if (ObjRelocations.Count>0) and
  738. not assigned(data) then
  739. internalerror(200205183);
  740. for i:=0 to ObjRelocations.Count-1 do
  741. begin
  742. objreloc:=TObjRelocation(ObjRelocations[i]);
  743. if objreloc.typ=RELOC_NONE then
  744. continue;
  745. if objreloc.typ=RELOC_ZERO then
  746. begin
  747. data.Seek(objreloc.dataoffset);
  748. zero:=0;
  749. data.Write(zero,4);
  750. continue;
  751. end;
  752. data.Seek(objreloc.dataoffset);
  753. data.Read(address,4);
  754. if assigned(objreloc.symbol) then
  755. begin
  756. relocsec:=objreloc.symbol.objsection;
  757. relocval:=objreloc.symbol.address;
  758. end
  759. else
  760. if assigned(objreloc.objsection) then
  761. begin
  762. relocsec:=objreloc.objsection;
  763. relocval:=objreloc.objsection.mempos
  764. end
  765. else
  766. internalerror(200205183);
  767. { Only debug section are allowed to have }
  768. if not relocsec.used and
  769. not(oso_debug in secoptions) then
  770. internalerror(200603061);
  771. case objreloc.typ of
  772. RELOC_RELATIVE :
  773. begin
  774. address:=address-mempos+relocval;
  775. if TCoffObjData(objdata).win32 then
  776. dec(address,objreloc.dataoffset+4);
  777. end;
  778. RELOC_RVA :
  779. begin
  780. { fixup address when the symbol was known in defined object }
  781. if (relocsec.objdata=objdata) then
  782. dec(address,TCoffObjSection(relocsec).orgmempos);
  783. {$ifdef arm}
  784. if (relocsec.objdata=objdata) and not TCoffObjData(objdata).eVCobj then
  785. inc(address, relocsec.MemPos)
  786. else
  787. {$endif arm}
  788. inc(address,relocval);
  789. end;
  790. RELOC_SECREL32 :
  791. begin
  792. { fixup address when the symbol was known in defined object }
  793. if (relocsec.objdata=objdata) then
  794. dec(address,TCoffObjSection(relocsec).mempos);
  795. inc(address,relocval);
  796. end;
  797. {$ifdef arm}
  798. RELOC_RELATIVE_24:
  799. begin
  800. relocval:=longint(relocval - mempos - objreloc.dataoffset) shr 2 - 2;
  801. address:=address or (relocval and $ffffff);
  802. relocval:=relocval shr 24;
  803. if (relocval<>$3f) and (relocval<>0) then
  804. internalerror(200606085); { offset overflow }
  805. end;
  806. {$endif arm}
  807. {$ifdef x86_64}
  808. { 64 bit coff only }
  809. RELOC_RELATIVE_1:
  810. begin
  811. address:=address-mempos+relocval;
  812. dec(address,objreloc.dataoffset+1);
  813. end;
  814. RELOC_RELATIVE_2:
  815. begin
  816. address:=address-mempos+relocval;
  817. dec(address,objreloc.dataoffset+2);
  818. end;
  819. RELOC_RELATIVE_3:
  820. begin
  821. address:=address-mempos+relocval;
  822. dec(address,objreloc.dataoffset+3);
  823. end;
  824. RELOC_RELATIVE_4:
  825. begin
  826. address:=address-mempos+relocval;
  827. dec(address,objreloc.dataoffset+4);
  828. end;
  829. RELOC_RELATIVE_5:
  830. begin
  831. address:=address-mempos+relocval;
  832. dec(address,objreloc.dataoffset+5);
  833. end;
  834. RELOC_ABSOLUTE32,
  835. {$endif x86_64}
  836. RELOC_ABSOLUTE :
  837. begin
  838. if oso_common in relocsec.secoptions then
  839. dec(address,objreloc.orgsize)
  840. else
  841. begin
  842. { fixup address when the symbol was known in defined object }
  843. if (relocsec.objdata=objdata) then
  844. dec(address,TCoffObjSection(relocsec).orgmempos);
  845. end;
  846. {$ifdef arm}
  847. if (relocsec.objdata=objdata) and not TCoffObjData(objdata).eVCobj then
  848. inc(address, relocsec.MemPos)
  849. else
  850. {$endif arm}
  851. inc(address,relocval);
  852. inc(address,relocsec.objdata.imagebase);
  853. end;
  854. else
  855. internalerror(200604014);
  856. end;
  857. data.Seek(objreloc.dataoffset);
  858. data.Write(address,4);
  859. end;
  860. end;
  861. {****************************************************************************
  862. TDJCoffObjSection
  863. ****************************************************************************}
  864. constructor TDJCoffObjSection.create(AList:TFPHashObjectList;const aname:string;aalign:shortint;aoptions:TObjSectionOptions);
  865. begin
  866. inherited create(alist,aname,aalign,aoptions);
  867. end;
  868. {****************************************************************************
  869. TPECoffObjSection
  870. ****************************************************************************}
  871. constructor TPECoffObjSection.create(AList:TFPHashObjectList;const aname:string;aalign:shortint;aoptions:TObjSectionOptions);
  872. begin
  873. inherited create(alist,aname,aalign,aoptions);
  874. end;
  875. {****************************************************************************
  876. TCoffObjData
  877. ****************************************************************************}
  878. constructor TCoffObjData.createcoff(const n:string;awin32:boolean;acObjSection:TObjSectionClass);
  879. begin
  880. inherited create(n);
  881. CObjSection:=ACObjSection;
  882. win32:=awin32;
  883. { we need at least the following 3 ObjSections }
  884. createsection(sec_code);
  885. createsection(sec_data);
  886. createsection(sec_bss);
  887. end;
  888. destructor TCoffObjData.destroy;
  889. begin
  890. inherited destroy;
  891. end;
  892. function TCoffObjData.sectionname(atype:TAsmSectiontype;const aname:string;aorder:TAsmSectionOrder):string;
  893. var
  894. sep : string[3];
  895. secname : string;
  896. begin
  897. secname:=coffsecnames[atype];
  898. if create_smartlink_sections and
  899. (aname<>'') then
  900. begin
  901. case aorder of
  902. secorder_begin :
  903. sep:='.b_';
  904. secorder_end :
  905. sep:='.z_';
  906. else
  907. sep:='.n_';
  908. end;
  909. result:=secname+sep+aname
  910. end
  911. else
  912. result:=secname;
  913. end;
  914. procedure TCoffObjData.CreateDebugSections;
  915. begin
  916. if target_dbg.id=dbg_stabs then
  917. begin
  918. stabssec:=createsection(sec_stab);
  919. stabstrsec:=createsection(sec_stabstr);
  920. end;
  921. end;
  922. procedure TCoffObjData.writereloc(data:aint;len:aword;p:TObjSymbol;reloctype:TObjRelocationType);
  923. var
  924. curraddr,
  925. symaddr : aword;
  926. begin
  927. if CurrObjSec=nil then
  928. internalerror(200403072);
  929. if assigned(p) then
  930. begin
  931. { current address }
  932. curraddr:=CurrObjSec.mempos+CurrObjSec.Size;
  933. { external/common symbols don't have a fixed memory position yet }
  934. if (p.bind=AB_COMMON) then
  935. begin
  936. { For go32v2 we need to use the size as address }
  937. if not win32 then
  938. symaddr:=p.size
  939. else
  940. symaddr:=0;
  941. end
  942. else
  943. symaddr:=p.address;
  944. { no symbol relocation need inside a section }
  945. if (p.objsection=CurrObjSec) and
  946. (p.bind<>AB_COMMON) then
  947. begin
  948. case reloctype of
  949. RELOC_ABSOLUTE :
  950. begin
  951. CurrObjSec.addsectionreloc(curraddr,CurrObjSec,RELOC_ABSOLUTE);
  952. inc(data,symaddr);
  953. end;
  954. {$ifdef x86_64}
  955. RELOC_ABSOLUTE32 :
  956. begin
  957. CurrObjSec.addsectionreloc(curraddr,CurrObjSec,RELOC_ABSOLUTE32);
  958. inc(data,symaddr);
  959. end;
  960. {$endif x86_64}
  961. RELOC_RELATIVE :
  962. begin
  963. inc(data,symaddr-len-CurrObjSec.Size);
  964. end;
  965. RELOC_RVA :
  966. begin
  967. CurrObjSec.addsectionreloc(curraddr,CurrObjSec,RELOC_RVA);
  968. inc(data,symaddr);
  969. end;
  970. else
  971. internalerror(200604013);
  972. end;
  973. end
  974. else
  975. begin
  976. if (p.objsection<>nil) and
  977. (p.bind<>AB_COMMON) and
  978. (reloctype<>RELOC_RELATIVE) then
  979. CurrObjSec.addsectionreloc(curraddr,p.objsection,reloctype)
  980. else
  981. CurrObjSec.addsymreloc(curraddr,p,reloctype);
  982. if (not win32) or
  983. ((reloctype<>RELOC_RELATIVE) and (p.objsection<>nil)) then
  984. inc(data,symaddr);
  985. if reloctype=RELOC_RELATIVE then
  986. begin
  987. if win32 then
  988. dec(data,len-4)
  989. else
  990. dec(data,len+CurrObjSec.Size);
  991. end;
  992. end;
  993. end
  994. else
  995. begin
  996. if reloctype=RELOC_RVA then
  997. internalerror(200603033);
  998. end;
  999. CurrObjSec.write(data,len);
  1000. end;
  1001. procedure TCoffObjData.afteralloc;
  1002. var
  1003. mempos : qword;
  1004. i : longint;
  1005. begin
  1006. inherited afteralloc;
  1007. { DJ Coff requires mempositions }
  1008. if not win32 then
  1009. begin
  1010. mempos:=0;
  1011. for i:=0 to ObjSectionList.Count-1 do
  1012. mempos:=TObjSection(ObjSectionList[i]).setmempos(mempos);
  1013. end;
  1014. end;
  1015. {****************************************************************************
  1016. TDJCoffObjData
  1017. ****************************************************************************}
  1018. constructor TDJCoffObjData.create(const n:string);
  1019. begin
  1020. inherited createcoff(n,false,TDJCoffObjSection);
  1021. end;
  1022. {****************************************************************************
  1023. TPECoffObjData
  1024. ****************************************************************************}
  1025. constructor TPECoffObjData.create(const n:string);
  1026. begin
  1027. inherited createcoff(n,true,TPECoffObjSection);
  1028. end;
  1029. {****************************************************************************
  1030. TCoffObjOutput
  1031. ****************************************************************************}
  1032. constructor TCoffObjOutput.createcoff(AWriter:TObjectWriter;awin32:boolean);
  1033. begin
  1034. inherited create(AWriter);
  1035. win32:=awin32;
  1036. end;
  1037. destructor TCoffObjOutput.destroy;
  1038. begin
  1039. if assigned(FCoffSyms) then
  1040. FCoffSyms.free;
  1041. if assigned(FCoffStrs) then
  1042. FCoffStrs.free;
  1043. inherited destroy;
  1044. end;
  1045. procedure TCoffObjOutput.write_symbol(const name:string;value:aword;section:smallint;typ,aux:byte);
  1046. var
  1047. sym : coffsymbol;
  1048. begin
  1049. FillChar(sym,sizeof(sym),0);
  1050. { symbolname }
  1051. if length(name)>8 then
  1052. begin
  1053. sym.strpos:=FCoffStrs.size+4;
  1054. FCoffStrs.writestr(name);
  1055. FCoffStrs.writestr(#0);
  1056. end
  1057. else
  1058. move(name[1],sym.name,length(name));
  1059. sym.value:=value;
  1060. sym.section:=section;
  1061. sym.typ:=typ;
  1062. sym.aux:=aux;
  1063. inc(symidx);
  1064. FCoffSyms.write(sym,sizeof(sym));
  1065. end;
  1066. procedure TCoffObjOutput.section_write_symbol(p:TObject;arg:pointer);
  1067. var
  1068. secrec : coffsectionrec;
  1069. begin
  1070. with TCoffObjSection(p) do
  1071. begin
  1072. secidx:=symidx div 2;
  1073. secsymidx:=symidx;
  1074. write_symbol(name,mempos,secidx,COFF_SYM_SECTION,1);
  1075. { AUX }
  1076. fillchar(secrec,sizeof(secrec),0);
  1077. secrec.len:=Size;
  1078. secrec.nrelocs:=ObjRelocations.count;
  1079. inc(symidx);
  1080. FCoffSyms.write(secrec,sizeof(secrec));
  1081. end;
  1082. end;
  1083. procedure TCoffObjOutput.section_write_relocs(p:TObject;arg:pointer);
  1084. var
  1085. i : longint;
  1086. rel : coffreloc;
  1087. objreloc : TObjRelocation;
  1088. begin
  1089. for i:=0 to TObjSection(p).ObjRelocations.Count-1 do
  1090. begin
  1091. objreloc:=TObjRelocation(TObjSection(p).ObjRelocations[i]);
  1092. rel.address:=objreloc.dataoffset;
  1093. if assigned(objreloc.symbol) then
  1094. begin
  1095. if (objreloc.symbol.bind=AB_LOCAL) then
  1096. rel.sym:=objreloc.symbol.objsection.secsymidx
  1097. else
  1098. begin
  1099. if objreloc.symbol.symidx=-1 then
  1100. internalerror(200602233);
  1101. rel.sym:=objreloc.symbol.symidx;
  1102. end;
  1103. end
  1104. else
  1105. begin
  1106. if objreloc.objsection<>nil then
  1107. rel.sym:=objreloc.objsection.secsymidx
  1108. else
  1109. rel.sym:=0;
  1110. end;
  1111. case objreloc.typ of
  1112. {$ifdef arm}
  1113. RELOC_ABSOLUTE :
  1114. rel.reloctype:=IMAGE_REL_ARM_ADDR32;
  1115. { I've no idea if this is correct (FK):
  1116. RELOC_RELATIVE :
  1117. rel.reloctype:=IMAGE_REL_ARM_GPREL12;
  1118. }
  1119. RELOC_RVA :
  1120. rel.reloctype:=IMAGE_REL_ARM_ADDR32NB;
  1121. RELOC_SECREL32 :
  1122. rel.reloctype:=IMAGE_REL_ARM_SECREL;
  1123. {$endif arm}
  1124. {$ifdef i386}
  1125. RELOC_RELATIVE :
  1126. rel.reloctype:=IMAGE_REL_I386_PCRLONG;
  1127. RELOC_ABSOLUTE :
  1128. rel.reloctype:=IMAGE_REL_I386_DIR32;
  1129. RELOC_RVA :
  1130. rel.reloctype:=IMAGE_REL_I386_IMAGEBASE;
  1131. RELOC_SECREL32 :
  1132. rel.reloctype:=IMAGE_REL_I386_SECREL32;
  1133. {$endif i386}
  1134. {$ifdef x86_64}
  1135. RELOC_RELATIVE :
  1136. rel.reloctype:=IMAGE_REL_AMD64_REL32;
  1137. RELOC_ABSOLUTE32 :
  1138. rel.reloctype:=IMAGE_REL_AMD64_ADDR32;
  1139. RELOC_ABSOLUTE :
  1140. rel.reloctype:=IMAGE_REL_AMD64_ADDR64;
  1141. RELOC_RVA :
  1142. rel.reloctype:=IMAGE_REL_AMD64_ADDR32NB;
  1143. RELOC_RELATIVE_1 :
  1144. rel.reloctype:=IMAGE_REL_AMD64_REL32_1;
  1145. RELOC_RELATIVE_2 :
  1146. rel.reloctype:=IMAGE_REL_AMD64_REL32_2;
  1147. RELOC_RELATIVE_3 :
  1148. rel.reloctype:=IMAGE_REL_AMD64_REL32_3;
  1149. RELOC_RELATIVE_4 :
  1150. rel.reloctype:=IMAGE_REL_AMD64_REL32_4;
  1151. RELOC_RELATIVE_5 :
  1152. rel.reloctype:=IMAGE_REL_AMD64_REL32_5;
  1153. RELOC_SECREL32 :
  1154. rel.reloctype:=IMAGE_REL_AMD64_SECREL;
  1155. {$endif x86_64}
  1156. else
  1157. internalerror(200603312);
  1158. end;
  1159. FWriter.write(rel,sizeof(rel));
  1160. end;
  1161. end;
  1162. procedure TCoffObjOutput.create_symbols(data:TObjData);
  1163. var
  1164. filename : string[18];
  1165. sectionval : word;
  1166. globalval : byte;
  1167. i : longint;
  1168. value : aword;
  1169. objsym : TObjSymbol;
  1170. begin
  1171. with TCoffObjData(data) do
  1172. begin
  1173. symidx:=0;
  1174. { The `.file' record, and the file name auxiliary record }
  1175. write_symbol('.file', 0, -2, COFF_SYM_FILE, 1);
  1176. fillchar(filename,sizeof(filename),0);
  1177. filename:=ExtractFileName(current_module.mainsource^);
  1178. inc(symidx);
  1179. FCoffSyms.write(filename[1],sizeof(filename)-1);
  1180. { Sections }
  1181. ObjSectionList.ForEachCall(@section_write_symbol,nil);
  1182. { ObjSymbols }
  1183. for i:=0 to ObjSymbolList.Count-1 do
  1184. begin
  1185. objsym:=TObjSymbol(ObjSymbolList[i]);
  1186. if (objsym.typ=AT_LABEL) and (objsym.bind=AB_LOCAL) then
  1187. continue;
  1188. case objsym.bind of
  1189. AB_GLOBAL :
  1190. begin
  1191. globalval:=2;
  1192. sectionval:=TCoffObjSection(objsym.objsection).secidx;
  1193. value:=objsym.address;
  1194. end;
  1195. AB_LOCAL :
  1196. begin
  1197. globalval:=3;
  1198. sectionval:=TCoffObjSection(objsym.objsection).secidx;
  1199. value:=objsym.address;
  1200. end;
  1201. else
  1202. begin
  1203. globalval:=2;
  1204. sectionval:=0;
  1205. value:=objsym.size;
  1206. end;
  1207. end;
  1208. { symbolname }
  1209. objsym.symidx:=symidx;
  1210. write_symbol(objsym.name,value,sectionval,globalval,0);
  1211. end;
  1212. end;
  1213. end;
  1214. procedure TCoffObjOutput.section_set_datapos(p:TObject;arg:pointer);
  1215. begin
  1216. TObjSection(p).setdatapos(paword(arg)^);
  1217. end;
  1218. procedure TCoffObjOutput.section_set_reloc_datapos(p:TObject;arg:pointer);
  1219. begin
  1220. TCoffObjSection(p).coffrelocpos:=paint(arg)^;
  1221. inc(paint(arg)^,sizeof(coffreloc)*TObjSection(p).ObjRelocations.count);
  1222. end;
  1223. procedure TCoffObjOutput.section_write_header(p:TObject;arg:pointer);
  1224. var
  1225. sechdr : tcoffsechdr;
  1226. s : string;
  1227. strpos : aword;
  1228. begin
  1229. with TCoffObjSection(p) do
  1230. begin
  1231. fillchar(sechdr,sizeof(sechdr),0);
  1232. s:=name;
  1233. if length(s)>8 then
  1234. begin
  1235. strpos:=FCoffStrs.size+4;
  1236. FCoffStrs.writestr(s);
  1237. FCoffStrs.writestr(#0);
  1238. s:='/'+ToStr(strpos);
  1239. end;
  1240. move(s[1],sechdr.name,length(s));
  1241. if not win32 then
  1242. begin
  1243. sechdr.rvaofs:=mempos;
  1244. sechdr.vsize:=mempos;
  1245. end
  1246. else
  1247. begin
  1248. if not(oso_data in secoptions) then
  1249. sechdr.vsize:=Size;
  1250. end;
  1251. sechdr.DataSize:=size;
  1252. if (Size>0) and
  1253. (oso_data in secoptions) then
  1254. sechdr.datapos:=datapos;
  1255. sechdr.nrelocs:=ObjRelocations.count;
  1256. sechdr.relocpos:=coffrelocpos;
  1257. if win32 then
  1258. sechdr.flags:=peencodesechdrflags(secoptions,secalign)
  1259. else
  1260. sechdr.flags:=djencodesechdrflags(secoptions);
  1261. FWriter.write(sechdr,sizeof(sechdr));
  1262. end;
  1263. end;
  1264. procedure TCoffObjOutput.section_write_data(p:TObject;arg:pointer);
  1265. begin
  1266. with TObjSection(p) do
  1267. begin
  1268. if assigned(data) then
  1269. begin
  1270. FWriter.writezeros(dataalignbytes);
  1271. if Datapos<>FWriter.ObjSize then
  1272. internalerror(200603052);
  1273. FWriter.writearray(data);
  1274. end;
  1275. end;
  1276. end;
  1277. function TCoffObjOutput.writedata(data:TObjData):boolean;
  1278. var
  1279. orgdatapos,
  1280. datapos,
  1281. sympos : aword;
  1282. i : longint;
  1283. gotreloc : boolean;
  1284. header : tcoffheader;
  1285. begin
  1286. result:=false;
  1287. FCoffSyms:=TDynamicArray.Create(SymbolMaxGrow);
  1288. FCoffStrs:=TDynamicArray.Create(StrsMaxGrow);
  1289. with TCoffObjData(data) do
  1290. begin
  1291. { Create Symbol Table }
  1292. create_symbols(data);
  1293. { Calculate the filepositions }
  1294. datapos:=sizeof(tcoffheader)+sizeof(tcoffsechdr)*ObjSectionList.Count;
  1295. { Sections first }
  1296. ObjSectionList.ForEachCall(@section_set_datapos,@datapos);
  1297. { relocs }
  1298. orgdatapos:=datapos;
  1299. ObjSectionList.ForEachCall(@section_set_reloc_datapos,@datapos);
  1300. gotreloc:=(orgdatapos<>datapos);
  1301. { Symbols }
  1302. sympos:=datapos;
  1303. { Generate COFF header }
  1304. fillchar(header,sizeof(tcoffheader),0);
  1305. header.mach:=COFF_MAGIC;
  1306. header.nsects:=ObjSectionList.Count;
  1307. header.sympos:=sympos;
  1308. header.syms:=symidx;
  1309. if win32 then
  1310. begin
  1311. {$ifdef arm}
  1312. header.flag:=PE_FILE_32BIT_MACHINE or
  1313. PE_FILE_LINE_NUMS_STRIPPED or PE_FILE_LOCAL_SYMS_STRIPPED;
  1314. {$else arm}
  1315. header.flag:=PE_FILE_BYTES_REVERSED_LO or PE_FILE_32BIT_MACHINE or
  1316. PE_FILE_LINE_NUMS_STRIPPED or PE_FILE_LOCAL_SYMS_STRIPPED;
  1317. {$endif arm}
  1318. if not gotreloc then
  1319. header.flag:=header.flag or PE_FILE_RELOCS_STRIPPED;
  1320. end
  1321. else
  1322. begin
  1323. header.flag:=COFF_FLAG_AR32WR or COFF_FLAG_NOLINES or COFF_FLAG_NOLSYMS;
  1324. if not gotreloc then
  1325. header.flag:=header.flag or COFF_FLAG_NORELOCS;
  1326. end;
  1327. FWriter.write(header,sizeof(header));
  1328. { Section headers }
  1329. ObjSectionList.ForEachCall(@section_write_header,nil);
  1330. { ObjSections }
  1331. ObjSectionList.ForEachCall(@section_write_data,nil);
  1332. { Relocs }
  1333. ObjSectionList.ForEachCall(@section_write_relocs,nil);
  1334. { ObjSymbols }
  1335. if Sympos<>FWriter.ObjSize then
  1336. internalerror(200603051);
  1337. FWriter.writearray(FCoffSyms);
  1338. { Strings }
  1339. i:=FCoffStrs.size+4;
  1340. FWriter.write(i,4);
  1341. FWriter.writearray(FCoffStrs);
  1342. end;
  1343. FCoffStrs.Free;
  1344. FCoffStrs:=nil;
  1345. FCoffSyms.Free;
  1346. FCoffSyms:=nil;
  1347. end;
  1348. constructor TDJCoffObjOutput.create(AWriter:TObjectWriter);
  1349. begin
  1350. inherited createcoff(AWriter,false);
  1351. cobjdata:=TDJCoffObjData;
  1352. end;
  1353. constructor TPECoffObjOutput.create(AWriter:TObjectWriter);
  1354. begin
  1355. inherited createcoff(AWriter,true);
  1356. cobjdata:=TPECoffObjData;
  1357. end;
  1358. {****************************************************************************
  1359. TCoffObjInput
  1360. ****************************************************************************}
  1361. constructor TCoffObjInput.createcoff(awin32:boolean);
  1362. begin
  1363. inherited create;
  1364. win32:=awin32;
  1365. FSymTbl:=nil;
  1366. end;
  1367. destructor TCoffObjInput.destroy;
  1368. begin
  1369. if assigned(FCoffSyms) then
  1370. FCoffSyms.free;
  1371. if assigned(FCoffStrs) then
  1372. FCoffStrs.free;
  1373. if assigned(FSymTbl) then
  1374. freemem(FSymTbl);
  1375. if assigned(FSecTbl) then
  1376. freemem(FSecTbl);
  1377. inherited destroy;
  1378. end;
  1379. function TCoffObjInput.GetSection(secidx:longint):TObjSection;
  1380. begin
  1381. result:=nil;
  1382. if (secidx<1) or (secidx>FSecCount) then
  1383. begin
  1384. InputError('Failed reading coff file, invalid section index');
  1385. exit;
  1386. end;
  1387. result:=FSecTbl^[secidx];
  1388. end;
  1389. function TCoffObjInput.Read_str(strpos:longword):string;
  1390. begin
  1391. FCoffStrs.Seek(strpos-4);
  1392. FCoffStrs.Read(result[1],255);
  1393. result[255]:=#0;
  1394. result[0]:=chr(strlen(@result[1]));
  1395. if result='' then
  1396. Internalerror(200205172);
  1397. end;
  1398. procedure TCoffObjInput.read_relocs(s:TCoffObjSection);
  1399. var
  1400. rel : coffreloc;
  1401. rel_type : TObjRelocationType;
  1402. i : longint;
  1403. p : TObjSymbol;
  1404. begin
  1405. for i:=1 to s.coffrelocs do
  1406. begin
  1407. FReader.read(rel,sizeof(rel));
  1408. case rel.reloctype of
  1409. {$ifdef arm}
  1410. IMAGE_REL_ARM_ABSOLUTE:
  1411. rel_type:=RELOC_NONE;
  1412. IMAGE_REL_ARM_ADDR32:
  1413. rel_type:=RELOC_ABSOLUTE;
  1414. IMAGE_REL_ARM_ADDR32NB:
  1415. rel_type:=RELOC_RVA;
  1416. IMAGE_REL_ARM_BRANCH24:
  1417. rel_type:=RELOC_RELATIVE_24;
  1418. {$endif arm}
  1419. {$ifdef i386}
  1420. IMAGE_REL_I386_PCRLONG :
  1421. rel_type:=RELOC_RELATIVE;
  1422. IMAGE_REL_I386_DIR32 :
  1423. rel_type:=RELOC_ABSOLUTE;
  1424. IMAGE_REL_I386_IMAGEBASE :
  1425. rel_type:=RELOC_RVA;
  1426. IMAGE_REL_I386_SECREL32 :
  1427. rel_type:=RELOC_SECREL32;
  1428. {$endif i386}
  1429. {$ifdef x86_64}
  1430. IMAGE_REL_AMD64_REL32:
  1431. rel_type:=RELOC_RELATIVE;
  1432. IMAGE_REL_AMD64_ADDR32:
  1433. rel_type:=RELOC_ABSOLUTE32;
  1434. IMAGE_REL_AMD64_ADDR64:
  1435. rel_type:=RELOC_ABSOLUTE;
  1436. IMAGE_REL_AMD64_ADDR32NB:
  1437. rel_type:=RELOC_RVA;
  1438. IMAGE_REL_AMD64_REL32_1:
  1439. rel_type:=RELOC_RELATIVE_1;
  1440. IMAGE_REL_AMD64_REL32_2:
  1441. rel_type:=RELOC_RELATIVE_2;
  1442. IMAGE_REL_AMD64_REL32_3:
  1443. rel_type:=RELOC_RELATIVE_3;
  1444. IMAGE_REL_AMD64_REL32_4:
  1445. rel_type:=RELOC_RELATIVE_4;
  1446. IMAGE_REL_AMD64_REL32_5:
  1447. rel_type:=RELOC_RELATIVE_5;
  1448. IMAGE_REL_AMD64_SECREL:
  1449. rel_type:=RELOC_SECREL32;
  1450. {$endif x86_64}
  1451. else
  1452. begin
  1453. InputError('Failed reading coff file, illegal reloctype $'+system.hexstr(rel.reloctype,4));
  1454. exit;
  1455. end;
  1456. end;
  1457. p:=FSymTbl^[rel.sym].sym;
  1458. if assigned(p) then
  1459. s.addsymsizereloc(rel.address-s.mempos,p,FSymTbl^[rel.sym].orgsize,rel_type)
  1460. else
  1461. begin
  1462. InputError('Failed reading coff file, can''t resolve symbol of relocation');
  1463. exit;
  1464. end;
  1465. end;
  1466. end;
  1467. procedure TCoffObjInput.read_symbols(objdata:TObjData);
  1468. var
  1469. size,
  1470. address,
  1471. nsyms,
  1472. symidx : aint;
  1473. i : longint;
  1474. sym : coffsymbol;
  1475. objsym : TObjSymbol;
  1476. bind : Tasmsymbind;
  1477. strname : string;
  1478. auxrec : array[0..17] of byte;
  1479. objsec : TObjSection;
  1480. begin
  1481. with TCoffObjData(objdata) do
  1482. begin
  1483. nsyms:=FCoffSyms.Size div sizeof(CoffSymbol);
  1484. { Allocate memory for symidx -> TObjSymbol table }
  1485. GetMem(FSymTbl,nsyms*sizeof(TObjSymbolrec));
  1486. FillChar(FSymTbl^,nsyms*sizeof(TObjSymbolrec),0);
  1487. { Load the Symbols }
  1488. FCoffSyms.Seek(0);
  1489. symidx:=0;
  1490. while (symidx<nsyms) do
  1491. begin
  1492. FCoffSyms.Read(sym,sizeof(sym));
  1493. if plongint(@sym.name)^<>0 then
  1494. begin
  1495. move(sym.name,strname[1],8);
  1496. strname[9]:=#0;
  1497. strname[0]:=chr(strlen(@strname[1]));
  1498. if strname='' then
  1499. Internalerror(200205171);
  1500. end
  1501. else
  1502. strname:=Read_str(sym.strpos);
  1503. bind:=AB_EXTERNAL;
  1504. size:=0;
  1505. address:=0;
  1506. objsym:=nil;
  1507. objsec:=nil;
  1508. case sym.typ of
  1509. COFF_SYM_GLOBAL :
  1510. begin
  1511. if sym.section=0 then
  1512. begin
  1513. if sym.value=0 then
  1514. bind:=AB_EXTERNAL
  1515. else
  1516. begin
  1517. bind:=AB_COMMON;
  1518. size:=sym.value;
  1519. end;
  1520. end
  1521. else
  1522. begin
  1523. bind:=AB_GLOBAL;
  1524. objsec:=GetSection(sym.section);
  1525. if sym.value>=objsec.mempos then
  1526. address:=sym.value-objsec.mempos;
  1527. end;
  1528. objsym:=CreateSymbol(strname);
  1529. objsym.bind:=bind;
  1530. objsym.typ:=AT_FUNCTION;
  1531. objsym.objsection:=objsec;
  1532. objsym.offset:=address;
  1533. objsym.size:=size;
  1534. { Register in ObjSection }
  1535. if assigned(objsec) then
  1536. objsec.AddSymbolDefine(objsym);
  1537. end;
  1538. COFF_SYM_LABEL,
  1539. COFF_SYM_LOCAL :
  1540. begin
  1541. { do not add constants (section=-1) }
  1542. if sym.section<>-1 then
  1543. begin
  1544. bind:=AB_LOCAL;
  1545. objsec:=GetSection(sym.section);
  1546. if sym.value>=objsec.mempos then
  1547. address:=sym.value-objsec.mempos;
  1548. objsym:=CreateSymbol(strname);
  1549. objsym.bind:=bind;
  1550. objsym.typ:=AT_FUNCTION;
  1551. objsym.objsection:=objsec;
  1552. objsym.offset:=address;
  1553. objsym.size:=size;
  1554. end;
  1555. end;
  1556. COFF_SYM_SECTION :
  1557. begin
  1558. if sym.section=0 then
  1559. InputError('Failed reading coff file, illegal section');
  1560. objsec:=GetSection(sym.section);
  1561. if assigned(objsec) then
  1562. begin
  1563. if sym.value>=objsec.mempos then
  1564. address:=sym.value-objsec.mempos;
  1565. objsym:=CreateSymbol(strname);
  1566. objsym.bind:=AB_LOCAL;
  1567. objsym.typ:=AT_FUNCTION;
  1568. objsym.objsection:=objsec;
  1569. objsym.offset:=address;
  1570. objsym.size:=size;
  1571. end;
  1572. end;
  1573. COFF_SYM_FUNCTION,
  1574. COFF_SYM_FILE :
  1575. ;
  1576. else
  1577. internalerror(200602232);
  1578. end;
  1579. FSymTbl^[symidx].sym:=objsym;
  1580. FSymTbl^[symidx].orgsize:=size;
  1581. { read aux records }
  1582. for i:=1 to sym.aux do
  1583. begin
  1584. FCoffSyms.Read(auxrec,sizeof(auxrec));
  1585. inc(symidx);
  1586. end;
  1587. inc(symidx);
  1588. end;
  1589. end;
  1590. end;
  1591. procedure TCoffObjInput.ObjSections_read_data(p:TObject;arg:pointer);
  1592. begin
  1593. with TCoffObjSection(p) do
  1594. begin
  1595. { Skip debug sections }
  1596. if (oso_debug in secoptions) and
  1597. (cs_link_strip in current_settings.globalswitches) and
  1598. not(cs_link_separate_dbg_file in current_settings.globalswitches) then
  1599. exit;
  1600. if assigned(data) then
  1601. begin
  1602. FReader.Seek(datapos);
  1603. if not FReader.ReadArray(data,Size) then
  1604. begin
  1605. Comment(V_Error,'Error reading coff file, can''t read object data');
  1606. exit;
  1607. end;
  1608. end;
  1609. end;
  1610. end;
  1611. procedure TCoffObjInput.ObjSections_read_relocs(p:TObject;arg:pointer);
  1612. begin
  1613. with TCoffObjSection(p) do
  1614. begin
  1615. { Skip debug sections }
  1616. if (oso_debug in secoptions) and
  1617. (cs_link_strip in current_settings.globalswitches) and
  1618. not(cs_link_separate_dbg_file in current_settings.globalswitches) then
  1619. exit;
  1620. if coffrelocs>0 then
  1621. begin
  1622. FReader.Seek(coffrelocpos);
  1623. read_relocs(TCoffObjSection(p));
  1624. end;
  1625. end;
  1626. end;
  1627. function TCoffObjInput.ReadObjData(AReader:TObjectreader;objdata:TObjData):boolean;
  1628. var
  1629. secalign : shortint;
  1630. strsize,
  1631. strpos,
  1632. i : longint;
  1633. code : longint;
  1634. objsec : TCoffObjSection;
  1635. secoptions : TObjSectionOptions;
  1636. header : tcoffheader;
  1637. sechdr : tcoffsechdr;
  1638. secname : string;
  1639. secnamebuf : array[0..15] of char;
  1640. begin
  1641. FReader:=AReader;
  1642. InputFileName:=AReader.FileName;
  1643. result:=false;
  1644. FCoffSyms:=TDynamicArray.Create(SymbolMaxGrow);
  1645. FCoffStrs:=TDynamicArray.Create(StrsMaxGrow);
  1646. with TCoffObjData(objdata) do
  1647. begin
  1648. { Read COFF header }
  1649. if not AReader.read(header,sizeof(tcoffheader)) then
  1650. begin
  1651. InputError('Can''t read COFF Header');
  1652. exit;
  1653. end;
  1654. if header.mach<>COFF_MAGIC then
  1655. begin
  1656. InputError('Illegal COFF Magic');
  1657. exit;
  1658. end;
  1659. {$ifdef arm}
  1660. eVCobj:=header.flag=$100;
  1661. {$endif arm}
  1662. { Strings }
  1663. AReader.Seek(header.sympos+header.syms*sizeof(CoffSymbol));
  1664. if not AReader.Read(strsize,4) then
  1665. begin
  1666. InputError('Error reading COFF Symtable');
  1667. exit;
  1668. end;
  1669. if (strsize>4) and not AReader.ReadArray(FCoffStrs,Strsize-4) then
  1670. begin
  1671. InputError('Error reading COFF Symtable');
  1672. exit;
  1673. end;
  1674. { Section headers }
  1675. { Allocate SecIdx -> TObjSection table, secidx is 1-based }
  1676. FSecCount:=header.nsects;
  1677. GetMem(FSecTbl,(header.nsects+1)*sizeof(TObjSection));
  1678. FillChar(FSecTbl^,(header.nsects+1)*sizeof(TObjSection),0);
  1679. AReader.Seek(sizeof(tcoffheader)+header.opthdr);
  1680. for i:=1 to header.nsects do
  1681. begin
  1682. if not AReader.read(sechdr,sizeof(sechdr)) then
  1683. begin
  1684. InputError('Error reading COFF Section Headers');
  1685. exit;
  1686. end;
  1687. move(sechdr.name,secnamebuf,8);
  1688. secnamebuf[8]:=#0;
  1689. secname:=strpas(secnamebuf);
  1690. if secname[1]='/' then
  1691. begin
  1692. Val(Copy(secname,2,8),strpos,code);
  1693. if code=0 then
  1694. secname:=Read_str(strpos)
  1695. else
  1696. begin
  1697. InputError('Error reading COFF Section Headers');
  1698. secname:='error';
  1699. end;
  1700. end;
  1701. if win32 then
  1702. pedecodesechdrflags(secname,sechdr.flags,secoptions,secalign)
  1703. else
  1704. begin
  1705. djdecodesechdrflags(secname,sechdr.flags);
  1706. secalign:=sizeof(pint);
  1707. end;
  1708. if (Length(secname)>3) and (secname[2] in ['e','f','i','p','r']) then
  1709. begin
  1710. if (Copy(secname,1,6)='.edata') or
  1711. (Copy(secname,1,5)='.rsrc') or
  1712. (Copy(secname,1,6)='.pdata') or
  1713. (Copy(secname,1,4)='.fpc') then
  1714. include(secoptions,oso_keep);
  1715. if (Copy(secname,1,6)='.idata') then
  1716. begin
  1717. { TODO: idata keep can maybe replaced with grouping of text and idata}
  1718. include(secoptions,oso_keep);
  1719. secname:=secname + '.' + ExtractFileName(InputFileName);
  1720. end;
  1721. end;
  1722. objsec:=TCoffObjSection(createsection(secname,secalign,secoptions,false));
  1723. FSecTbl^[i]:=objsec;
  1724. if not win32 then
  1725. objsec.mempos:=sechdr.rvaofs;
  1726. objsec.orgmempos:=sechdr.rvaofs;
  1727. objsec.coffrelocs:=sechdr.nrelocs;
  1728. objsec.coffrelocpos:=sechdr.relocpos;
  1729. objsec.datapos:=sechdr.datapos;
  1730. objsec.Size:=sechdr.dataSize;
  1731. end;
  1732. { ObjSymbols }
  1733. AReader.Seek(header.sympos);
  1734. if not AReader.ReadArray(FCoffSyms,header.syms*sizeof(CoffSymbol)) then
  1735. begin
  1736. Comment(V_Error,'Error reading coff file');
  1737. exit;
  1738. end;
  1739. { Insert all ObjSymbols }
  1740. read_symbols(objdata);
  1741. { Section Data }
  1742. ObjSectionList.ForEachCall(@objsections_read_data,nil);
  1743. { Relocs }
  1744. ObjSectionList.ForEachCall(@objsections_read_relocs,nil);
  1745. end;
  1746. FCoffStrs.Free;
  1747. FCoffStrs:=nil;
  1748. FCoffSyms.Free;
  1749. FCoffSyms:=nil;
  1750. result:=true;
  1751. end;
  1752. constructor TDJCoffObjInput.create;
  1753. begin
  1754. inherited createcoff(false);
  1755. cobjdata:=TDJCoffObjData;
  1756. end;
  1757. constructor TPECoffObjInput.create;
  1758. begin
  1759. inherited createcoff(true);
  1760. cobjdata:=TPECoffObjData;
  1761. end;
  1762. {****************************************************************************
  1763. TCoffexesection
  1764. ****************************************************************************}
  1765. constructor TCoffExeSection.createcoff(AList:TFPHashObjectList;const n:string;awin32:boolean);
  1766. begin
  1767. inherited create(AList,n);
  1768. win32:=awin32;
  1769. end;
  1770. constructor TDJCoffExeSection.create(AList:TFPHashObjectList;const n:string);
  1771. begin
  1772. inherited createcoff(AList,n,false);
  1773. end;
  1774. constructor TPECoffExeSection.create(AList:TFPHashObjectList;const n:string);
  1775. begin
  1776. inherited createcoff(AList,n,false);
  1777. end;
  1778. {****************************************************************************
  1779. TCoffexeoutput
  1780. ****************************************************************************}
  1781. constructor TCoffexeoutput.createcoff(awin32:boolean);
  1782. begin
  1783. inherited create;
  1784. win32:=awin32;
  1785. if target_info.system in [system_x86_64_win64] then
  1786. MaxMemPos:=$FFFFFFFF
  1787. else
  1788. if target_info.system in system_wince then
  1789. MaxMemPos:=$1FFFFFF
  1790. else
  1791. MaxMemPos:=$7FFFFFFF;
  1792. end;
  1793. procedure TCoffexeoutput.write_symbol(const name:string;value:aword;section:smallint;typ,aux:byte);
  1794. var
  1795. sym : coffsymbol;
  1796. begin
  1797. FillChar(sym,sizeof(sym),0);
  1798. if length(name)>8 then
  1799. begin
  1800. sym.strpos:=FCoffStrs.size+4;
  1801. FCoffStrs.writestr(name);
  1802. FCoffStrs.writestr(#0);
  1803. end
  1804. else
  1805. move(name[1],sym.name,length(name));
  1806. sym.value:=value;
  1807. sym.section:=section;
  1808. sym.typ:=typ;
  1809. sym.aux:=aux;
  1810. FWriter.write(sym,sizeof(sym));
  1811. end;
  1812. procedure TCoffexeoutput.globalsyms_write_symbol(p:TObject;arg:pointer);
  1813. var
  1814. secval,
  1815. value : aint;
  1816. globalval : byte;
  1817. exesec : TExeSection;
  1818. begin
  1819. if not assigned(texesymbol(p).objsymbol) then
  1820. internalerror(200603053);
  1821. with texesymbol(p).objsymbol do
  1822. begin
  1823. exesec:=TExeSection(objsection.exesection);
  1824. { There is no exesection defined for special internal symbols
  1825. like __image_base__ }
  1826. if assigned(exesec) then
  1827. begin
  1828. secval:=exesec.secsymidx;
  1829. value:=address-exesec.mempos;
  1830. end
  1831. else
  1832. begin
  1833. secval:=-1;
  1834. value:=address;
  1835. end;
  1836. if bind=AB_LOCAL then
  1837. globalval:=3
  1838. else
  1839. globalval:=2;
  1840. { reloctype address to the section in the executable }
  1841. write_symbol(name,value,secval,globalval,0);
  1842. end;
  1843. end;
  1844. procedure TCoffexeoutput.ExeSectionList_write_header(p:TObject;arg:pointer);
  1845. var
  1846. sechdr : tcoffsechdr;
  1847. s : string;
  1848. strpos : aword;
  1849. begin
  1850. with tExeSection(p) do
  1851. begin
  1852. fillchar(sechdr,sizeof(sechdr),0);
  1853. s:=name;
  1854. if length(s)>8 then
  1855. begin
  1856. strpos:=FCoffStrs.size+4;
  1857. FCoffStrs.writestr(s);
  1858. FCoffStrs.writestr(#0);
  1859. s:='/'+ToStr(strpos);
  1860. end;
  1861. move(s[1],sechdr.name,length(s));
  1862. sechdr.rvaofs:=mempos;
  1863. if win32 then
  1864. sechdr.vsize:=Size
  1865. else
  1866. sechdr.vsize:=mempos;
  1867. { sechdr.dataSize is size of initilized data. For .bss section it must be zero }
  1868. if (Name <> '.bss') then
  1869. sechdr.dataSize:=Size;
  1870. if (sechdr.dataSize>0) and
  1871. (oso_data in SecOptions) then
  1872. sechdr.datapos:=datapos;
  1873. sechdr.nrelocs:=0;
  1874. sechdr.relocpos:=0;
  1875. if win32 then
  1876. sechdr.flags:=peencodesechdrflags(SecOptions,SecAlign)
  1877. else
  1878. sechdr.flags:=djencodesechdrflags(SecOptions);
  1879. FWriter.write(sechdr,sizeof(sechdr));
  1880. end;
  1881. end;
  1882. procedure TCoffexeoutput.ExeSectionList_pass2_header(p:TObject;arg:pointer);
  1883. begin
  1884. with TExeSection(p) do
  1885. begin
  1886. { The debuginfo sections should already be stripped }
  1887. { if (ExeWriteMode=ewm_exeonly) and
  1888. (oso_debug in SecOptions) then
  1889. internalerror(200801161); }
  1890. inc(plongint(arg)^);
  1891. secsymidx:=plongint(arg)^;
  1892. end;
  1893. end;
  1894. procedure Tcoffexeoutput.ExeSectionList_write_Data(p:TObject;arg:pointer);
  1895. var
  1896. objsec : TObjSection;
  1897. i : longint;
  1898. begin
  1899. with texesection(p) do
  1900. begin
  1901. { don't write normal section if writing only debug info }
  1902. if (ExeWriteMode=ewm_dbgonly) and
  1903. not(oso_debug in SecOptions) then
  1904. exit;
  1905. if oso_data in secoptions then
  1906. begin
  1907. FWriter.Writezeros(Align(FWriter.Size,SectionDataAlign)-FWriter.Size);
  1908. for i:=0 to ObjSectionList.Count-1 do
  1909. begin
  1910. objsec:=TObjSection(ObjSectionList[i]);
  1911. if oso_data in objsec.secoptions then
  1912. begin
  1913. if not assigned(objsec.data) then
  1914. internalerror(200603042);
  1915. FWriter.writezeros(objsec.dataalignbytes);
  1916. if objsec.DataPos<>FWriter.Size then
  1917. internalerror(200602251);
  1918. FWriter.writearray(objsec.data);
  1919. end;
  1920. end;
  1921. end;
  1922. end;
  1923. end;
  1924. function tcoffexeoutput.totalheadersize:longword;
  1925. var
  1926. stubsize,
  1927. optheadersize : longword;
  1928. begin
  1929. if win32 then
  1930. begin
  1931. stubsize:=sizeof(win32stub)+sizeof(pemagic);
  1932. optheadersize:=sizeof(tcoffpeoptheader);
  1933. end
  1934. else
  1935. begin
  1936. stubsize:=sizeof(go32v2stub);
  1937. optheadersize:=sizeof(coffdjoptheader);
  1938. end;
  1939. result:=stubsize+sizeof(tcoffheader)+optheadersize;
  1940. end;
  1941. procedure tcoffexeoutput.MemPos_Header;
  1942. begin
  1943. { calculate start positions after the headers }
  1944. currmempos:=totalheadersize+sizeof(tcoffsechdr)*longword(ExeSectionList.Count-2);
  1945. end;
  1946. procedure tcoffexeoutput.DataPos_Header;
  1947. begin
  1948. { retrieve amount of sections }
  1949. nsects:=0;
  1950. ExeSectionList.ForEachCall(@ExeSectionList_pass2_header,@nsects);
  1951. { calculate start positions after the headers }
  1952. currdatapos:=totalheadersize+longword(nsects)*sizeof(tcoffsechdr);
  1953. end;
  1954. procedure tcoffexeoutput.DataPos_Symbols;
  1955. begin
  1956. inherited DataPos_Symbols;
  1957. { Calculating symbols position and size }
  1958. nsyms:=ExeSymbolList.Count;
  1959. sympos:=CurrDataPos;
  1960. inc(CurrDataPos,sizeof(coffsymbol)*nsyms);
  1961. end;
  1962. function TCoffexeoutput.writedata:boolean;
  1963. var
  1964. i : longword;
  1965. header : tcoffheader;
  1966. djoptheader : coffdjoptheader;
  1967. peoptheader : tcoffpeoptheader;
  1968. textExeSec,
  1969. dataExeSec,
  1970. bssExeSec,
  1971. idataExeSec : TExeSection;
  1972. hassymbols,
  1973. writeDbgStrings : boolean;
  1974. procedure UpdateDataDir(const secname:string;idx:longint);
  1975. var
  1976. exesec : TExeSection;
  1977. begin
  1978. exesec:=FindExeSection(secname);
  1979. if assigned(exesec) then
  1980. begin
  1981. peoptheader.DataDirectory[idx].vaddr:=exesec.mempos;
  1982. peoptheader.DataDirectory[idx].size:=exesec.Size;
  1983. end;
  1984. end;
  1985. begin
  1986. result:=false;
  1987. FCoffSyms:=TDynamicArray.Create(SymbolMaxGrow);
  1988. FCoffStrs:=TDynamicArray.Create(StrsMaxGrow);
  1989. textExeSec:=FindExeSection('.text');
  1990. dataExeSec:=FindExeSection('.data');
  1991. bssExeSec:=FindExeSection('.bss');
  1992. if not assigned(TextExeSec) or
  1993. not assigned(DataExeSec) then
  1994. internalerror(200602231);
  1995. { do we need to write symbols? }
  1996. hassymbols:=(ExeWriteMode=ewm_dbgonly) or
  1997. (
  1998. (ExeWriteMode=ewm_exefull) and
  1999. not(cs_link_strip in current_settings.globalswitches)
  2000. );
  2001. writeDbgStrings:=hassymbols or ((ExeWriteMode=ewm_exeonly) and (cs_link_separate_dbg_file in current_settings.globalswitches));
  2002. { Stub }
  2003. if win32 then
  2004. begin
  2005. FWriter.write(win32stub,sizeof(win32stub));
  2006. FWriter.write(pemagic,sizeof(pemagic));
  2007. end
  2008. else
  2009. FWriter.write(go32v2stub,sizeof(go32v2stub));
  2010. { Initial header, will be updated later }
  2011. fillchar(header,sizeof(header),0);
  2012. header.mach:=COFF_MAGIC;
  2013. header.nsects:=nsects;
  2014. if writeDbgStrings then
  2015. header.sympos:=sympos;
  2016. if hassymbols then
  2017. header.syms:=nsyms;
  2018. if win32 then
  2019. header.opthdr:=sizeof(tcoffpeoptheader)
  2020. else
  2021. header.opthdr:=sizeof(coffdjoptheader);
  2022. if win32 then
  2023. begin
  2024. header.flag:=PE_FILE_EXECUTABLE_IMAGE or PE_FILE_LINE_NUMS_STRIPPED;
  2025. if target_info.system in [system_x86_64_win64] then
  2026. header.flag:=header.flag or PE_FILE_LARGE_ADDRESS_AWARE
  2027. else
  2028. header.flag:=header.flag or PE_FILE_32BIT_MACHINE;
  2029. if IsSharedLibrary then
  2030. header.flag:=header.flag or PE_FILE_DLL;
  2031. if FindExeSection('.reloc')=nil then
  2032. header.flag:=header.flag or PE_FILE_RELOCS_STRIPPED;
  2033. if (FindExeSection('.stab')=nil) and
  2034. (FindExeSection('.debug_info')=nil) and
  2035. (FindExeSection('.gnu_debuglink')=nil) then
  2036. header.flag:=header.flag or PE_FILE_DEBUG_STRIPPED;
  2037. if not hassymbols then
  2038. header.flag:=header.flag or PE_FILE_LOCAL_SYMS_STRIPPED;
  2039. if SetPEFlagsSetExplicity then
  2040. header.flag:=header.flag or peflags;
  2041. end
  2042. else
  2043. header.flag:=COFF_FLAG_AR32WR or COFF_FLAG_EXE or COFF_FLAG_NORELOCS or COFF_FLAG_NOLINES;
  2044. FWriter.write(header,sizeof(header));
  2045. { Optional COFF Header }
  2046. if win32 then
  2047. begin
  2048. fillchar(peoptheader,sizeof(peoptheader),0);
  2049. peoptheader.magic:=COFF_OPT_MAGIC;
  2050. peoptheader.MajorLinkerVersion:=ord(version_nr)-ord('0');
  2051. peoptheader.MinorLinkerVersion:=(ord(release_nr)-ord('0'))*10 + (ord(patch_nr)-ord('0'));
  2052. peoptheader.tsize:=TextExeSec.Size;
  2053. peoptheader.dsize:=DataExeSec.Size;
  2054. if assigned(BSSExeSec) then
  2055. peoptheader.bsize:=BSSExeSec.Size;
  2056. peoptheader.text_start:=TextExeSec.mempos;
  2057. {$ifndef x86_64}
  2058. peoptheader.data_start:=DataExeSec.mempos;
  2059. {$endif x86_64}
  2060. peoptheader.entry:=EntrySym.Address;
  2061. peoptheader.ImageBase:=ImageBase;
  2062. peoptheader.SectionAlignment:=SectionMemAlign;
  2063. peoptheader.FileAlignment:=SectionDataAlign;
  2064. peoptheader.MajorOperatingSystemVersion:=4;
  2065. peoptheader.MinorOperatingSystemVersion:=0;
  2066. peoptheader.MajorImageVersion:=dllmajor;
  2067. peoptheader.MinorImageVersion:=dllminor;
  2068. if target_info.system in system_wince then
  2069. peoptheader.MajorSubsystemVersion:=3
  2070. else
  2071. peoptheader.MajorSubsystemVersion:=4;
  2072. peoptheader.MinorSubsystemVersion:=0;
  2073. peoptheader.Win32Version:=0;
  2074. peoptheader.SizeOfImage:=Align(CurrMemPos,SectionMemAlign);
  2075. peoptheader.SizeOfHeaders:=textExeSec.DataPos;
  2076. peoptheader.CheckSum:=0;
  2077. if target_info.system in system_wince then
  2078. peoptheader.Subsystem:=PE_SUBSYSTEM_WINDOWS_CE_GUI
  2079. else
  2080. if apptype=app_gui then
  2081. peoptheader.Subsystem:=PE_SUBSYSTEM_WINDOWS_GUI
  2082. else
  2083. peoptheader.Subsystem:=PE_SUBSYSTEM_WINDOWS_CUI;
  2084. peoptheader.DllCharacteristics:=0;
  2085. peoptheader.SizeOfStackReserve:=stacksize;
  2086. peoptheader.SizeOfStackCommit:=$1000;
  2087. if MinStackSizeSetExplicity then
  2088. peoptheader.SizeOfStackCommit:=minstacksize;
  2089. if MaxStackSizeSetExplicity then
  2090. peoptheader.SizeOfStackReserve:=maxstacksize;
  2091. peoptheader.SizeOfHeapReserve:=$100000;
  2092. peoptheader.SizeOfHeapCommit:=$1000;
  2093. peoptheader.NumberOfRvaAndSizes:=PE_DATADIR_ENTRIES;
  2094. UpdateDataDir('.idata',PE_DATADIR_IDATA);
  2095. UpdateDataDir('.edata',PE_DATADIR_EDATA);
  2096. UpdateDataDir('.rsrc',PE_DATADIR_RSRC);
  2097. UpdateDataDir('.pdata',PE_DATADIR_PDATA);
  2098. UpdateDataDir('.reloc',PE_DATADIR_RELOC);
  2099. FWriter.write(peoptheader,sizeof(peoptheader));
  2100. end
  2101. else
  2102. begin
  2103. fillchar(djoptheader,sizeof(djoptheader),0);
  2104. djoptheader.magic:=COFF_OPT_MAGIC;
  2105. djoptheader.tsize:=TextExeSec.Size;
  2106. djoptheader.dsize:=DataExeSec.Size;
  2107. if assigned(BSSExeSec) then
  2108. djoptheader.bsize:=BSSExeSec.Size;
  2109. djoptheader.text_start:=TextExeSec.mempos;
  2110. djoptheader.data_start:=DataExeSec.mempos;
  2111. djoptheader.entry:=EntrySym.offset;
  2112. FWriter.write(djoptheader,sizeof(djoptheader));
  2113. end;
  2114. { For some unknown reason WM 6.1 requires .idata section to be read only.
  2115. Otherwise it refuses to load DLLs greater than 64KB.
  2116. Earlier versions of WinCE load DLLs regardless of .idata flags. }
  2117. if target_info.system in system_wince then
  2118. begin
  2119. idataExeSec:=FindExeSection('.idata');
  2120. if idataExeSec<>nil then
  2121. idataExeSec.SecOptions:=idataExeSec.SecOptions - [oso_write] + [oso_readonly];
  2122. end;
  2123. { Section headers }
  2124. ExeSectionList.ForEachCall(@ExeSectionList_write_header,nil);
  2125. { Section data }
  2126. ExeSectionList.ForEachCall(@ExeSectionList_write_data,nil);
  2127. { Optional Symbols }
  2128. if SymPos<>FWriter.Size then
  2129. internalerror(200602252);
  2130. if hassymbols then
  2131. ExeSymbolList.ForEachCall(@globalsyms_write_symbol,nil);
  2132. if writeDbgStrings then
  2133. begin
  2134. { Strings }
  2135. i:=FCoffStrs.size+4;
  2136. FWriter.write(i,4);
  2137. FWriter.writearray(FCoffStrs);
  2138. end;
  2139. { Release }
  2140. FCoffStrs.Free;
  2141. FCoffSyms.Free;
  2142. result:=true;
  2143. end;
  2144. function IdataObjSectionCompare(Item1, Item2: Pointer): Integer;
  2145. var
  2146. I1 : TObjSection absolute Item1;
  2147. I2 : TObjSection absolute Item2;
  2148. begin
  2149. Result:=CompareStr(I1.Name,I2.Name);
  2150. end;
  2151. procedure TCoffexeoutput.Order_ObjSectionList(ObjSectionList: TFPObjectList);
  2152. begin
  2153. if CurrExeSec.Name = '.idata' then
  2154. ObjSectionList.Sort(@IdataObjSectionCompare);
  2155. end;
  2156. constructor TDJCoffexeoutput.create;
  2157. begin
  2158. inherited createcoff(false);
  2159. CExeSection:=TDJCoffExeSection;
  2160. CObjData:=TPECoffObjData;
  2161. end;
  2162. constructor TPECoffexeoutput.create;
  2163. begin
  2164. inherited createcoff(true);
  2165. CExeSection:=TPECoffExeSection;
  2166. CObjData:=TPECoffObjData;
  2167. end;
  2168. procedure TPECoffexeoutput.GenerateLibraryImports(ImportLibraryList:TFPHashObjectList);
  2169. var
  2170. textobjsection,
  2171. idata2objsection,
  2172. idata4objsection,
  2173. idata5objsection,
  2174. idata6objsection,
  2175. idata7objsection : TObjSection;
  2176. idata2label : TObjSymbol;
  2177. basedllname : string;
  2178. procedure StartImport(const dllname:string);
  2179. var
  2180. idata4label,
  2181. idata5label,
  2182. idata7label : TObjSymbol;
  2183. emptyint : longint;
  2184. begin
  2185. if assigned(exemap) then
  2186. begin
  2187. exemap.Add('');
  2188. exemap.Add('Importing from DLL '+dllname);
  2189. end;
  2190. emptyint:=0;
  2191. basedllname:=ExtractFileName(dllname);
  2192. idata2objsection:=internalobjdata.createsection(sec_idata2,basedllname);
  2193. idata2label:=internalobjdata.SymbolDefine('__imp_dir_'+basedllname,AB_LOCAL,AT_DATA);
  2194. idata4objsection:=internalobjdata.createsection(sec_idata4,basedllname);
  2195. idata4label:=internalobjdata.SymbolDefine('__imp_names_'+basedllname,AB_LOCAL,AT_DATA);
  2196. idata5objsection:=internalobjdata.createsection(sec_idata5,basedllname);
  2197. idata5label:=internalobjdata.SymbolDefine('__imp_fixup_'+basedllname,AB_LOCAL,AT_DATA);
  2198. idata7objsection:=internalobjdata.createsection(sec_idata7,basedllname);
  2199. idata7label:=internalobjdata.SymbolDefine('__imp_dll_'+basedllname,AB_LOCAL,AT_DATA);
  2200. { idata2 }
  2201. internalobjdata.SetSection(idata2objsection);
  2202. { dummy links to imports finalization }
  2203. internalobjdata.writereloc(0,0,internalobjdata.SymbolRef('__imp_names_end_'+basedllname),RELOC_NONE);
  2204. internalobjdata.writereloc(0,0,internalobjdata.SymbolRef('__imp_fixup_end_'+basedllname),RELOC_NONE);
  2205. { section data }
  2206. internalobjdata.writereloc(0,sizeof(longint),idata4label,RELOC_RVA);
  2207. internalobjdata.writebytes(emptyint,sizeof(emptyint));
  2208. internalobjdata.writebytes(emptyint,sizeof(emptyint));
  2209. internalobjdata.writereloc(0,sizeof(longint),idata7label,RELOC_RVA);
  2210. internalobjdata.writereloc(0,sizeof(longint),idata5label,RELOC_RVA);
  2211. { idata7 }
  2212. internalobjdata.SetSection(idata7objsection);
  2213. internalobjdata.writebytes(basedllname[1],length(basedllname));
  2214. internalobjdata.writebytes(emptyint,1);
  2215. end;
  2216. procedure EndImport;
  2217. var
  2218. emptyint : longint;
  2219. begin
  2220. emptyint:=0;
  2221. idata4objsection:=internalobjdata.createsection(sec_idata4, basedllname+'_z_');
  2222. internalobjdata.SymbolDefine('__imp_names_end_'+basedllname,AB_LOCAL,AT_DATA);
  2223. idata5objsection:=internalobjdata.createsection(sec_idata5, basedllname+'_z_');
  2224. internalobjdata.SymbolDefine('__imp_fixup_end_'+basedllname,AB_LOCAL,AT_DATA);
  2225. { idata4 }
  2226. internalobjdata.SetSection(idata4objsection);
  2227. internalobjdata.writebytes(emptyint,sizeof(emptyint));
  2228. if target_info.system=system_x86_64_win64 then
  2229. internalobjdata.writebytes(emptyint,sizeof(emptyint));
  2230. { idata5 }
  2231. internalobjdata.SetSection(idata5objsection);
  2232. internalobjdata.writebytes(emptyint,sizeof(emptyint));
  2233. if target_info.system=system_x86_64_win64 then
  2234. internalobjdata.writebytes(emptyint,sizeof(emptyint));
  2235. { be sure that this will not be removed }
  2236. idata4objsection.SecOptions:=idata4objsection.SecOptions + [oso_keep];
  2237. idata5objsection.SecOptions:=idata5objsection.SecOptions + [oso_keep];
  2238. end;
  2239. function AddImport(const afuncname,amangledname:string; AOrdNr:longint;isvar:boolean):TObjSymbol;
  2240. const
  2241. {$ifdef x86_64}
  2242. jmpopcode : array[0..2] of byte = (
  2243. $ff,$24,$25
  2244. );
  2245. {$else x86_64}
  2246. {$ifdef arm}
  2247. jmpopcode : array[0..7] of byte = (
  2248. $00,$c0,$9f,$e5, // ldr ip, [pc, #0]
  2249. $00,$f0,$9c,$e5 // ldr pc, [ip]
  2250. );
  2251. {$else arm}
  2252. jmpopcode : array[0..1] of byte = (
  2253. $ff,$25
  2254. );
  2255. {$endif arm}
  2256. {$endif x86_64}
  2257. nopopcodes : array[0..1] of byte = (
  2258. $90,$90
  2259. );
  2260. var
  2261. idata4label,
  2262. idata5label,
  2263. idata6label : TObjSymbol;
  2264. emptyint : longint;
  2265. secname,
  2266. num : string;
  2267. absordnr: word;
  2268. procedure WriteTableEntry;
  2269. var
  2270. ordint: dword;
  2271. begin
  2272. if AOrdNr <= 0 then
  2273. begin
  2274. { import by name }
  2275. internalobjdata.writereloc(0,sizeof(longint),idata6label,RELOC_RVA);
  2276. if target_info.system=system_x86_64_win64 then
  2277. internalobjdata.writebytes(emptyint,sizeof(emptyint));
  2278. end
  2279. else
  2280. begin
  2281. { import by ordinal }
  2282. ordint:=AOrdNr;
  2283. if target_info.system=system_x86_64_win64 then
  2284. begin
  2285. internalobjdata.writebytes(ordint,sizeof(ordint));
  2286. ordint:=$80000000;
  2287. internalobjdata.writebytes(ordint,sizeof(ordint));
  2288. end
  2289. else
  2290. begin
  2291. ordint:=ordint or $80000000;
  2292. internalobjdata.writebytes(ordint,sizeof(ordint));
  2293. end;
  2294. end;
  2295. end;
  2296. begin
  2297. result:=nil;
  2298. emptyint:=0;
  2299. if assigned(exemap) then
  2300. begin
  2301. if AOrdNr <= 0 then
  2302. exemap.Add(' Importing Function '+afuncname)
  2303. else
  2304. exemap.Add(' Importing Function '+afuncname+' (OrdNr='+tostr(AOrdNr)+')');
  2305. end;
  2306. with internalobjdata do
  2307. begin
  2308. secname:=basedllname+'_i_'+amangledname;
  2309. textobjsection:=createsection(sectionname(sec_code,secname,secorder_default),current_settings.alignment.procalign,sectiontype2options(sec_code) - [oso_keep]);
  2310. idata4objsection:=createsection(sec_idata4, secname);
  2311. idata5objsection:=createsection(sec_idata5, secname);
  2312. idata6objsection:=createsection(sec_idata6, secname);
  2313. end;
  2314. { idata6, import data (ordnr+name) }
  2315. internalobjdata.SetSection(idata6objsection);
  2316. inc(idatalabnr);
  2317. num:=tostr(idatalabnr);
  2318. idata6label:=internalobjdata.SymbolDefine('__imp_'+num,AB_LOCAL,AT_DATA);
  2319. absordnr:=Abs(AOrdNr);
  2320. { write index hint }
  2321. internalobjdata.writebytes(absordnr,2);
  2322. if AOrdNr <= 0 then
  2323. internalobjdata.writebytes(afuncname[1],length(afuncname));
  2324. internalobjdata.writebytes(emptyint,1);
  2325. internalobjdata.writebytes(emptyint,align(internalobjdata.CurrObjSec.size,2)-internalobjdata.CurrObjSec.size);
  2326. { idata4, import lookup table }
  2327. internalobjdata.SetSection(idata4objsection);
  2328. idata4label:=internalobjdata.SymbolDefine('__imp_lookup_'+num,AB_LOCAL,AT_DATA);
  2329. WriteTableEntry;
  2330. { idata5, import address table }
  2331. internalobjdata.SetSection(idata5objsection);
  2332. { dummy back links }
  2333. internalobjdata.writereloc(0,0,idata4label,RELOC_NONE);
  2334. internalobjdata.writereloc(0,0,idata2label,RELOC_NONE);
  2335. { section data }
  2336. if isvar then
  2337. result:=internalobjdata.SymbolDefine(amangledname,AB_GLOBAL,AT_DATA)
  2338. else
  2339. idata5label:=internalobjdata.SymbolDefine('__imp_'+amangledname,AB_LOCAL,AT_DATA);
  2340. WriteTableEntry;
  2341. { text, jmp }
  2342. if not isvar then
  2343. begin
  2344. internalobjdata.SetSection(textobjsection);
  2345. result:=internalobjdata.SymbolDefine('_'+amangledname,AB_GLOBAL,AT_FUNCTION);
  2346. internalobjdata.writebytes(jmpopcode,sizeof(jmpopcode));
  2347. internalobjdata.writereloc(0,sizeof(longint),idata5label,RELOC_ABSOLUTE32);
  2348. internalobjdata.writebytes(nopopcodes,align(internalobjdata.CurrObjSec.size,sizeof(nopopcodes))-internalobjdata.CurrObjSec.size);
  2349. end;
  2350. end;
  2351. var
  2352. i,j : longint;
  2353. ImportLibrary : TImportLibrary;
  2354. ImportSymbol : TImportSymbol;
  2355. exesym : TExeSymbol;
  2356. begin
  2357. for i:=0 to ImportLibraryList.Count-1 do
  2358. begin
  2359. ImportLibrary:=TImportLibrary(ImportLibraryList[i]);
  2360. idata2objsection:=nil;
  2361. idata4objsection:=nil;
  2362. idata5objsection:=nil;
  2363. idata6objsection:=nil;
  2364. idata7objsection:=nil;
  2365. for j:=0 to ImportLibrary.ImportSymbolList.Count-1 do
  2366. begin
  2367. ImportSymbol:=TImportSymbol(ImportLibrary.ImportSymbolList[j]);
  2368. exesym:=TExeSymbol(ExeSymbolList.Find(ImportSymbol.MangledName));
  2369. if assigned(exesym) and
  2370. (exesym.State<>symstate_defined) then
  2371. begin
  2372. if not assigned(idata2objsection) then
  2373. StartImport(ImportLibrary.Name);
  2374. exesym.objsymbol:=AddImport(ImportSymbol.Name,ImportSymbol.MangledName,ImportSymbol.OrdNr,ImportSymbol.IsVar);
  2375. exesym.State:=symstate_defined;
  2376. end;
  2377. end;
  2378. if assigned(idata2objsection) then
  2379. EndImport;
  2380. end;
  2381. PackUnresolvedExeSymbols('after DLL imports');
  2382. end;
  2383. procedure TPECoffexeoutput.GenerateRelocs;
  2384. var
  2385. pgaddr, hdrpos : longword;
  2386. procedure FinishBlock;
  2387. var
  2388. p,len : longint;
  2389. begin
  2390. if hdrpos = longword(-1) then
  2391. exit;
  2392. p:=0;
  2393. internalobjdata.writebytes(p,align(internalobjdata.CurrObjSec.size,4)-internalobjdata.CurrObjSec.size);
  2394. p:=internalObjData.CurrObjSec.Data.Pos;
  2395. internalObjData.CurrObjSec.Data.seek(hdrpos+4);
  2396. len:=p-hdrpos;
  2397. internalObjData.CurrObjSec.Data.write(len,4);
  2398. internalObjData.CurrObjSec.Data.seek(p);
  2399. hdrpos:=longword(-1);
  2400. end;
  2401. var
  2402. exesec : TExeSection;
  2403. objsec : TObjSection;
  2404. objreloc : TObjRelocation;
  2405. i,j,k : longint;
  2406. offset : longword;
  2407. w: word;
  2408. begin
  2409. if not RelocSection then
  2410. exit;
  2411. exesec:=FindExeSection('.reloc');
  2412. if exesec=nil then
  2413. exit;
  2414. objsec:=internalObjData.createsection('.reloc',0,exesec.SecOptions+[oso_data]);
  2415. exesec.AddObjSection(objsec);
  2416. pgaddr:=longword(-1);
  2417. hdrpos:=longword(-1);
  2418. for i:=0 to ExeSectionList.Count-1 do
  2419. begin
  2420. exesec:=TExeSection(ExeSectionList[i]);
  2421. for j:=0 to exesec.ObjSectionList.count-1 do
  2422. begin
  2423. objsec:=TObjSection(exesec.ObjSectionList[j]);
  2424. { create relocs only for sections which are loaded in memory }
  2425. if not (oso_load in objsec.SecOptions) then
  2426. continue;
  2427. for k:=0 to objsec.ObjRelocations.Count-1 do
  2428. begin
  2429. objreloc:=TObjRelocation(objsec.ObjRelocations[k]);
  2430. if not (objreloc.typ in [{$ifdef x86_64}RELOC_ABSOLUTE32,{$endif x86_64}RELOC_ABSOLUTE]) then
  2431. continue;
  2432. offset:=objsec.MemPos+objreloc.dataoffset;
  2433. if (offset<pgaddr) and (pgaddr<>longword(-1)) then
  2434. Internalerror(2007062701);
  2435. if (offset-pgaddr>=4096) or (pgaddr=longword(-1)) then
  2436. begin
  2437. FinishBlock;
  2438. pgaddr:=(offset div 4096)*4096;
  2439. hdrpos:=internalObjData.CurrObjSec.Data.Pos;
  2440. internalObjData.writebytes(pgaddr,4);
  2441. { Reserving space for block size. The size will be written later in FinishBlock }
  2442. internalObjData.writebytes(k,4);
  2443. end;
  2444. w:=(IMAGE_REL_BASED_HIGHLOW shl 12) or (offset-pgaddr);
  2445. internalObjData.writebytes(w,2);
  2446. end;
  2447. end;
  2448. end;
  2449. FinishBlock;
  2450. end;
  2451. procedure TPECoffexeoutput.Order_End;
  2452. var
  2453. exesec : TExeSection;
  2454. begin
  2455. inherited;
  2456. if not IsSharedLibrary then
  2457. exit;
  2458. exesec:=FindExeSection('.reloc');
  2459. if exesec=nil then
  2460. exit;
  2461. exesec.SecOptions:=exesec.SecOptions + [oso_Data,oso_keep,oso_load];
  2462. end;
  2463. procedure TPECoffexeoutput.MemPos_ExeSection(const aname:string);
  2464. begin
  2465. if aname='.reloc' then
  2466. GenerateRelocs;
  2467. inherited;
  2468. end;
  2469. {****************************************************************************
  2470. TDJCoffAssembler
  2471. ****************************************************************************}
  2472. constructor TDJCoffAssembler.Create(smart:boolean);
  2473. begin
  2474. inherited Create(smart);
  2475. CObjOutput:=TDJCoffObjOutput;
  2476. end;
  2477. {****************************************************************************
  2478. TPECoffAssembler
  2479. ****************************************************************************}
  2480. constructor TPECoffAssembler.Create(smart:boolean);
  2481. begin
  2482. inherited Create(smart);
  2483. CObjOutput:=TPECoffObjOutput;
  2484. end;
  2485. {*****************************************************************************
  2486. DLLReader
  2487. *****************************************************************************}
  2488. {$ifdef win32}
  2489. var
  2490. Wow64DisableWow64FsRedirection : function (var OldValue : pointer) : boolean;stdcall;
  2491. Wow64RevertWow64FsRedirection : function (OldValue : pointer) : boolean;stdcall;
  2492. {$endif win32}
  2493. function ReadDLLImports(const dllname:string;readdllproc:Treaddllproc):boolean;
  2494. type
  2495. TPECoffExpDir=packed record
  2496. flag,
  2497. stamp : cardinal;
  2498. Major,
  2499. Minor : word;
  2500. Name,
  2501. Base,
  2502. NumFuncs,
  2503. NumNames,
  2504. AddrFuncs,
  2505. AddrNames,
  2506. AddrOrds : cardinal;
  2507. end;
  2508. var
  2509. DLLReader : TObjectReader;
  2510. DosHeader : array[0..$7f] of byte;
  2511. PEMagic : array[0..3] of byte;
  2512. Header : TCoffHeader;
  2513. peheader : tcoffpeoptheader;
  2514. NameOfs,
  2515. newheaderofs : longword;
  2516. FuncName : string;
  2517. expdir : TPECoffExpDir;
  2518. i : longint;
  2519. found : boolean;
  2520. sechdr : tCoffSecHdr;
  2521. {$ifdef win32}
  2522. p : pointer;
  2523. {$endif win32}
  2524. begin
  2525. result:=false;
  2526. {$ifdef win32}
  2527. if (target_info.system=system_x86_64_win64) and
  2528. assigned(Wow64DisableWow64FsRedirection) then
  2529. Wow64DisableWow64FsRedirection(p);
  2530. {$endif win32}
  2531. DLLReader:=TObjectReader.Create;
  2532. DLLReader.OpenFile(dllname);
  2533. {$ifdef win32}
  2534. if (target_info.system=system_x86_64_win64) and
  2535. assigned(Wow64RevertWow64FsRedirection) then
  2536. Wow64RevertWow64FsRedirection(p);
  2537. {$endif win32}
  2538. if not DLLReader.Read(DosHeader,sizeof(DosHeader)) or
  2539. (DosHeader[0]<>$4d) or (DosHeader[1]<>$5a) then
  2540. begin
  2541. Comment(V_Error,'Invalid DLL '+dllname+', Dos Header invalid');
  2542. exit;
  2543. end;
  2544. newheaderofs:=cardinal(DosHeader[$3c]) or (DosHeader[$3d] shl 8) or (DosHeader[$3e] shl 16) or (DosHeader[$3f] shl 24);
  2545. DLLReader.Seek(newheaderofs);
  2546. if not DLLReader.Read(PEMagic,sizeof(PEMagic)) or
  2547. (PEMagic[0]<>$50) or (PEMagic[1]<>$45) or (PEMagic[2]<>$00) or (PEMagic[3]<>$00) then
  2548. begin
  2549. Comment(V_Error,'Invalid DLL '+dllname+': invalid magic code');
  2550. exit;
  2551. end;
  2552. if not DLLReader.Read(Header,sizeof(TCoffHeader)) or
  2553. (Header.mach<>COFF_MAGIC) or
  2554. (Header.opthdr<>sizeof(tcoffpeoptheader)) then
  2555. begin
  2556. Comment(V_Error,'Invalid DLL '+dllname+', invalid header size');
  2557. exit;
  2558. end;
  2559. { Read optheader }
  2560. DLLreader.Read(peheader,sizeof(tcoffpeoptheader));
  2561. { Section headers }
  2562. found:=false;
  2563. for i:=1 to header.nsects do
  2564. begin
  2565. if not DLLreader.read(sechdr,sizeof(sechdr)) then
  2566. begin
  2567. Comment(V_Error,'Error reading coff file '+DLLName);
  2568. exit;
  2569. end;
  2570. if (sechdr.rvaofs<=peheader.DataDirectory[PE_DATADIR_EDATA].vaddr) and
  2571. (peheader.DataDirectory[PE_DATADIR_EDATA].vaddr<sechdr.rvaofs+sechdr.vsize) then
  2572. begin
  2573. found:=true;
  2574. break;
  2575. end;
  2576. end;
  2577. if not found then
  2578. begin
  2579. Comment(V_Warning,'DLL '+DLLName+' does not contain any exports');
  2580. exit;
  2581. end;
  2582. { Process edata }
  2583. DLLReader.Seek(sechdr.datapos+peheader.DataDirectory[PE_DATADIR_EDATA].vaddr-sechdr.rvaofs);
  2584. DLLReader.Read(expdir,sizeof(expdir));
  2585. for i:=0 to expdir.NumNames-1 do
  2586. begin
  2587. DLLReader.Seek(sechdr.datapos+expdir.AddrNames-sechdr.rvaofs+i*4);
  2588. DLLReader.Read(NameOfs,4);
  2589. Dec(NameOfs,sechdr.rvaofs);
  2590. if (NameOfs<0) or
  2591. (NameOfs>sechdr.vsize) then
  2592. begin
  2593. Comment(V_Error,'DLL does contains invalid exports');
  2594. break;
  2595. end;
  2596. { Read Function name from DLL, prepend _ and terminate with #0 }
  2597. DLLReader.Seek(sechdr.datapos+NameOfs);
  2598. DLLReader.Read((@FuncName[1])^,sizeof(FuncName)-3);
  2599. FuncName[sizeof(FuncName)-1]:=#0;
  2600. FuncName[0]:=chr(Strlen(@FuncName[1]));
  2601. readdllproc(DLLName,FuncName);
  2602. end;
  2603. DLLReader.Free;
  2604. end;
  2605. {*****************************************************************************
  2606. Initialize
  2607. *****************************************************************************}
  2608. {$ifdef i386}
  2609. const
  2610. as_i386_coff_info : tasminfo =
  2611. (
  2612. id : as_i386_coff;
  2613. idtxt : 'COFF';
  2614. asmbin : '';
  2615. asmcmd : '';
  2616. supported_targets : [system_i386_go32v2];
  2617. flags : [af_outputbinary];
  2618. labelprefix : '.L';
  2619. comment : '';
  2620. );
  2621. as_i386_pecoff_info : tasminfo =
  2622. (
  2623. id : as_i386_pecoff;
  2624. idtxt : 'PECOFF';
  2625. asmbin : '';
  2626. asmcmd : '';
  2627. supported_targets : [system_i386_win32];
  2628. flags : [af_outputbinary,af_smartlink_sections];
  2629. labelprefix : '.L';
  2630. comment : '';
  2631. );
  2632. as_i386_pecoffwdosx_info : tasminfo =
  2633. (
  2634. id : as_i386_pecoffwdosx;
  2635. idtxt : 'PEWDOSX';
  2636. asmbin : '';
  2637. asmcmd : '';
  2638. supported_targets : [system_i386_wdosx];
  2639. flags : [af_outputbinary];
  2640. labelprefix : '.L';
  2641. comment : '';
  2642. );
  2643. as_i386_pecoffwince_info : tasminfo =
  2644. (
  2645. id : as_i386_pecoffwince;
  2646. idtxt : 'PECOFFWINCE';
  2647. asmbin : '';
  2648. asmcmd : '';
  2649. supported_targets : [system_i386_wince];
  2650. flags : [af_outputbinary,af_smartlink_sections];
  2651. labelprefix : '.L';
  2652. comment : '';
  2653. );
  2654. {$endif i386}
  2655. {$ifdef x86_64}
  2656. const
  2657. as_x86_64_pecoff_info : tasminfo =
  2658. (
  2659. id : as_x86_64_pecoff;
  2660. idtxt : 'PECOFF';
  2661. asmbin : '';
  2662. asmcmd : '';
  2663. supported_targets : [system_x86_64_win64];
  2664. flags : [af_outputbinary,af_smartlink_sections];
  2665. labelprefix : '.L';
  2666. comment : '';
  2667. );
  2668. {$endif x86_64}
  2669. {$ifdef arm}
  2670. const
  2671. as_arm_pecoffwince_info : tasminfo =
  2672. (
  2673. id : as_arm_pecoffwince;
  2674. idtxt : 'PECOFFWINCE';
  2675. asmbin : '';
  2676. asmcmd : '';
  2677. supported_targets : [system_arm_wince];
  2678. flags : [af_outputbinary];
  2679. labelprefix : '.L';
  2680. comment : '';
  2681. );
  2682. {$endif arm}
  2683. {$ifdef win32}
  2684. procedure SetupProcVars;
  2685. var
  2686. hinstLib : THandle;
  2687. begin
  2688. Wow64DisableWow64FsRedirection:=nil;
  2689. Wow64RevertWow64FsRedirection:=nil;
  2690. hinstLib:=LoadLibrary('kernel32.dll');
  2691. if hinstLib<>0 then
  2692. begin
  2693. pointer(Wow64DisableWow64FsRedirection):=GetProcAddress(hinstLib,'Wow64DisableWow64FsRedirection');
  2694. pointer(Wow64RevertWow64FsRedirection):=GetProcAddress(hinstLib,'Wow64RevertWow64FsRedirection');
  2695. FreeLibrary(hinstLib);
  2696. end;
  2697. end;
  2698. {$endif win32}
  2699. initialization
  2700. {$ifdef i386}
  2701. RegisterAssembler(as_i386_coff_info,TDJCoffAssembler);
  2702. RegisterAssembler(as_i386_pecoff_info,TPECoffAssembler);
  2703. RegisterAssembler(as_i386_pecoffwdosx_info,TPECoffAssembler);
  2704. RegisterAssembler(as_i386_pecoffwince_info,TPECoffAssembler);
  2705. {$endif i386}
  2706. {$ifdef x86_64}
  2707. RegisterAssembler(as_x86_64_pecoff_info,TPECoffAssembler);
  2708. {$endif x86_64}
  2709. {$ifdef arm}
  2710. RegisterAssembler(as_arm_pecoffwince_info,TPECoffAssembler);
  2711. {$endif arm}
  2712. {$ifdef win32}
  2713. SetupProcVars;
  2714. {$endif win32}
  2715. end.