ogcoff.pas 105 KB

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