ogcoff.pas 108 KB

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