ogcoff.pas 112 KB

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