ogbase.pas 127 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737
  1. {
  2. Copyright (c) 1998-2006 by Peter Vreman
  3. Contains the base stuff for binary object file writers
  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 ogbase;
  18. {$i fpcdefs.inc}
  19. interface
  20. uses
  21. { common }
  22. cutils,
  23. cclasses,
  24. { targets }
  25. systems,globtype,
  26. { outputwriters }
  27. owbase,
  28. { assembler }
  29. aasmbase,
  30. cpuinfo;
  31. type
  32. TObjSection = class;
  33. TObjData = class;
  34. TExeSection = class;
  35. TExeSymbol = class;
  36. TExeOutput = class;
  37. TObjRelocationType = (
  38. { Relocation to absolute address }
  39. RELOC_ABSOLUTE,
  40. {$ifdef x86_64}
  41. { 32bit Relocation to absolute address }
  42. RELOC_ABSOLUTE32,
  43. { 64 bit coff only }
  44. RELOC_RELATIVE_1,
  45. RELOC_RELATIVE_2,
  46. RELOC_RELATIVE_3,
  47. RELOC_RELATIVE_4,
  48. RELOC_RELATIVE_5,
  49. { PIC }
  50. RELOC_GOTPCREL,
  51. RELOC_PLT32,
  52. RELOC_TLSGD,
  53. RELOC_TPOFF,
  54. {$endif x86_64}
  55. {$ifdef i386}
  56. { PIC }
  57. RELOC_GOTPC,
  58. RELOC_GOT32,
  59. RELOC_PLT32,
  60. RELOC_TLSGD,
  61. RELOC_NTPOFF,
  62. {$endif i386}
  63. {$ifdef i8086}
  64. RELOC_ABSOLUTE32,
  65. RELOC_RELATIVE32,
  66. RELOC_FARPTR,
  67. RELOC_FARPTR_RELATIVEOFFSET,
  68. RELOC_FARPTR48,
  69. RELOC_FARPTR48_RELATIVEOFFSET,
  70. RELOC_SEG,
  71. RELOC_SEGREL,
  72. RELOC_DGROUP,
  73. RELOC_DGROUPREL,
  74. RELOC_FARDATASEG,
  75. RELOC_FARDATASEGREL,
  76. {$endif i8086}
  77. {$ifdef arm}
  78. RELOC_RELATIVE_24,
  79. RELOC_RELATIVE_CALL,
  80. RELOC_RELATIVE_24_THUMB,
  81. RELOC_RELATIVE_CALL_THUMB,
  82. RELOC_GOT32,
  83. RELOC_TPOFF,
  84. RELOC_TLSGD,
  85. RELOC_TLSDESC,
  86. RELOC_TLS_CALL,
  87. RELOC_ARM_CALL,
  88. {$endif arm}
  89. { Relative relocation }
  90. RELOC_RELATIVE,
  91. { PECoff (Windows) RVA relocation }
  92. RELOC_RVA,
  93. { PECoff (Windows) section relocation, required by DWARF2 debug info }
  94. RELOC_SECREL32,
  95. { Generate a 0 value at the place of the relocation,
  96. this is used to remove unused vtable entries }
  97. RELOC_ZERO,
  98. { No relocation is needed. It is used in ARM object files.
  99. Also internal linker use this reloc to make virtual (not real)
  100. links to some sections }
  101. RELOC_NONE,
  102. { Darwin relocation, using PAIR }
  103. RELOC_PIC_PAIR,
  104. { Relative to GOT/gp }
  105. RELOC_GOTOFF,
  106. { Untranslated target-specific value }
  107. RELOC_RAW,
  108. { offset in TLS block }
  109. RELOC_DTPOFF
  110. );
  111. {$if defined(x86_64)}
  112. { no special aliases for x86_64 }
  113. {$elseif defined(i8086)}
  114. const
  115. RELOC_ABSOLUTE16 = RELOC_ABSOLUTE;
  116. RELOC_RELATIVE16 = RELOC_RELATIVE;
  117. {$else}
  118. const
  119. RELOC_ABSOLUTE32 = RELOC_ABSOLUTE;
  120. {$endif}
  121. const
  122. { stab types }
  123. N_GSYM = $20;
  124. N_STSYM = 38; { initialized const }
  125. N_LCSYM = 40; { non initialized variable}
  126. N_Function = $24; { function or const }
  127. N_TextLine = $44;
  128. N_DataLine = $46;
  129. N_BssLine = $48;
  130. N_RSYM = $40; { register variable }
  131. N_LSYM = $80;
  132. N_tsym = 160;
  133. N_SourceFile = $64;
  134. N_IncludeFile = $84;
  135. N_BINCL = $82;
  136. N_EINCL = $A2;
  137. N_LBRAC = $C0;
  138. N_EXCL = $C2;
  139. N_RBRAC = $E0;
  140. { GNU extensions }
  141. debuglinkname='.gnu_debuglink';
  142. { TObjRelocation.flags }
  143. { 'ftype' field contains platform-specific value }
  144. rf_raw = 1;
  145. { relocation must be added to dynamic list }
  146. rf_dynamic = 2;
  147. { relocation target is absent/irrelevant (e.g. R_ARM_V4BX) }
  148. rf_nosymbol = 4;
  149. type
  150. TObjSectionOption = (
  151. { Has Data available in the file }
  152. oso_Data,
  153. { Is loaded into memory }
  154. oso_load,
  155. { Writable }
  156. oso_write,
  157. { Contains executable instructions }
  158. oso_executable,
  159. { Never discard section }
  160. oso_keep,
  161. { Procedure Linkage Table specific treatment }
  162. oso_plt,
  163. { Contains debug info and can be stripped }
  164. oso_debug,
  165. { Contains only strings }
  166. oso_strings,
  167. { Must be cloned when writing separate debug file }
  168. oso_debug_copy,
  169. { Has relocations with explicit addends (ELF-specific) }
  170. oso_rela_relocs,
  171. { Supports bss-like allocation of data, even though it is written in file (i.e. also has oso_Data) }
  172. oso_sparse_data,
  173. { Section to support the resolution of multiple symbols with the same name }
  174. oso_comdat,
  175. { section containing thread variables }
  176. oso_threadvar,
  177. { being a notes section }
  178. oso_note,
  179. { arm attributes section }
  180. oso_arm_attributes
  181. );
  182. TObjSectionOptions = set of TObjSectionOption;
  183. TObjSectionComdatSelection = (
  184. { Section is not a COMDAT section }
  185. oscs_none,
  186. { Select any of the symbols }
  187. oscs_any,
  188. { Select any symbol, but abort if they differ in size }
  189. oscs_same_size,
  190. { Select any symbol, but abort if they differ in size or content }
  191. oscs_exact_match,
  192. { Select the symbol only if the associated symbol is linked as well }
  193. oscs_associative,
  194. { Select the largest symbol }
  195. oscs_largest
  196. );
  197. {$ifdef i8086}
  198. { allow 32-bit sections on i8086. Useful for the dwarf debug info, as well
  199. as to allow linking 32-bit obj modules. }
  200. TObjSectionOfs = LongWord;
  201. {$else i8086}
  202. TObjSectionOfs = PUInt;
  203. {$endif i8086}
  204. TObjSectionGroup = class;
  205. TObjSymbol = class(TFPHashObject)
  206. public
  207. bind : TAsmsymbind;
  208. typ : TAsmsymtype;
  209. { Current assemble pass, used to detect duplicate labels }
  210. pass : byte;
  211. { how the symbol is referenced (target-specific bitfield) }
  212. refs : byte;
  213. symidx : longint;
  214. objsection : TObjSection;
  215. offset,
  216. size : TObjSectionOfs;
  217. { Used for external and common solving during linking }
  218. exesymbol : TExeSymbol;
  219. { Darwin asm is using indirect symbols resolving }
  220. indsymbol : TObjSymbol;
  221. { Used by the OMF object format and its complicated relocation records }
  222. group: TObjSectionGroup;
  223. {$ifdef ARM}
  224. ThumbFunc : boolean;
  225. {$endif ARM}
  226. constructor create(AList:TFPHashObjectList;const AName:string);
  227. function address:qword;
  228. procedure SetAddress(apass:byte;aobjsec:TObjSection;abind:TAsmsymbind;atyp:Tasmsymtype);
  229. function ObjData: TObjData;
  230. { string representation for the linker map file }
  231. function AddressStr(AImageBase: qword): string;virtual;
  232. end;
  233. TObjSymbolClass = class of TObjSymbol;
  234. { Stabs is common for all targets }
  235. TObjStabEntry=packed record
  236. strpos : longint;
  237. ntype : byte;
  238. nother : byte;
  239. ndesc : word;
  240. nvalue : longint;
  241. end;
  242. PObjStabEntry=^TObjStabEntry;
  243. TObjRelocation = class
  244. private
  245. function GetType:TObjRelocationType;
  246. procedure SetType(v:TObjRelocationType);
  247. public
  248. DataOffset,
  249. orgsize : TObjSectionOfs; { COFF: original size of the symbol to relocate }
  250. { ELF: explicit addend }
  251. symbol : TObjSymbol;
  252. objsection : TObjSection; { only used if symbol=nil }
  253. group : TObjSectionGroup; { only used if symbol=nil and objsection=nil }
  254. ftype : byte;
  255. size : byte;
  256. flags : byte;
  257. constructor CreateSymbol(ADataOffset:TObjSectionOfs;s:TObjSymbol;Atyp:TObjRelocationType);
  258. constructor CreateSection(ADataOffset:TObjSectionOfs;aobjsec:TObjSection;Atyp:TObjRelocationType);
  259. constructor CreateGroup(ADataOffset:TObjSectionOfs;grp:TObjSectionGroup;Atyp:TObjRelocationType);
  260. constructor CreateRaw(ADataOffset:TObjSectionOfs;s:TObjSymbol;ARawType:byte);
  261. function TargetName:TSymStr;
  262. property typ: TObjRelocationType read GetType write SetType;
  263. end;
  264. TObjSection = class(TFPHashObject)
  265. private
  266. FData : TDynamicArray;
  267. FSecOptions : TObjSectionOptions;
  268. FCachedFullName : pshortstring;
  269. FSizeLimit : TObjSectionOfs;
  270. procedure SetSecOptions(Aoptions:TObjSectionOptions);
  271. procedure SectionTooLargeError;
  272. public
  273. ObjData : TObjData;
  274. index : longword; { index of section in section headers }
  275. SecSymIdx : longint; { index for the section in symtab }
  276. SecAlign : longint; { alignment of the section }
  277. { section Data }
  278. Size,
  279. DataPos : TObjSectionOfs;
  280. MemPos : qword;
  281. Group : TObjSectionGroup;
  282. AssociativeSection : TObjSection;
  283. ComdatSelection : TObjSectionComdatSelection;
  284. DataAlignBytes : shortint;
  285. { Relocations (=references) to other sections }
  286. ObjRelocations : TFPObjectList;
  287. { executable linking }
  288. ExeSection : TExeSection;
  289. USed : Boolean;
  290. VTRefList : TFPObjectList;
  291. constructor create(AList:TFPHashObjectList;const Aname:string;Aalign:longint;Aoptions:TObjSectionOptions);virtual;
  292. destructor destroy;override;
  293. function write(const d;l:TObjSectionOfs):TObjSectionOfs;
  294. { writes string plus zero byte }
  295. function writestr(const s:string):TObjSectionOfs;
  296. function WriteZeros(l:longword):TObjSectionOfs;
  297. { writes content of s without null termination }
  298. function WriteBytes(const s:string):TObjSectionOfs;
  299. procedure writeReloc_internal(aTarget:TObjSection;offset:aword;len:byte;reltype:TObjRelocationType);virtual;
  300. function setmempos(mpos:qword):qword;
  301. procedure setDatapos(var dpos:TObjSectionOfs);
  302. procedure alloc(l:TObjSectionOfs);
  303. procedure addsymReloc(ofs:TObjSectionOfs;p:TObjSymbol;Reloctype:TObjRelocationType);
  304. procedure addsectionReloc(ofs:TObjSectionOfs;aobjsec:TObjSection;Reloctype:TObjRelocationType);
  305. procedure addrawReloc(ofs:TObjSectionOfs;p:TObjSymbol;RawReloctype:byte);
  306. procedure ReleaseData;
  307. function FullName:string;
  308. { string representation for the linker map file }
  309. function MemPosStr(AImageBase: qword): string;virtual;
  310. property Data:TDynamicArray read FData;
  311. property SecOptions:TObjSectionOptions read FSecOptions write SetSecOptions;
  312. property SizeLimit:TObjSectionOfs read FSizeLimit write FSizeLimit;
  313. end;
  314. TObjSectionClass = class of TObjSection;
  315. TObjSectionGroup = class(TFPHashObject)
  316. public
  317. index: longword; { index of group in group headers }
  318. members: array of TObjSection;
  319. iscomdat: boolean;
  320. end;
  321. TObjSectionGroupClass = class of TObjSectionGroup;
  322. TString80 = string[80];
  323. TObjSymbolList = class(TFPHashObjectList)
  324. public
  325. Owner: TObjData;
  326. end;
  327. {$ifdef i8086}
  328. { on i8086 we use a longint, to support 32-bit relocations as well (e.g.
  329. for allowing 386+ instructions with 32-bit addresses in inline asm code) }
  330. TRelocDataInt = longint;
  331. {$else i8086}
  332. TRelocDataInt = aint;
  333. {$endif i8086}
  334. TObjData = class(TLinkedListItem)
  335. private
  336. FCurrObjSec : TObjSection;
  337. FObjSectionList : TFPHashObjectList;
  338. FCObjSymbol : TObjSymbolClass;
  339. FCObjSection : TObjSectionClass;
  340. FCObjSectionGroup: TObjSectionGroupClass;
  341. { Symbols that will be defined in this object file }
  342. FObjSymbolList : TObjSymbolList;
  343. FCachedAsmSymbolList : TFPObjectList;
  344. { Special info sections that are written to during object generation }
  345. FStabsObjSec,
  346. FStabStrObjSec : TObjSection;
  347. FGroupsList : TFPHashObjectList;
  348. FCPUType : tcputype;
  349. procedure section_reset(p:TObject;arg:pointer);
  350. procedure section_afteralloc(p:TObject;arg:pointer);
  351. procedure section_afterwrite(p:TObject;arg:pointer);
  352. protected
  353. FName : TString80;
  354. property CObjSection:TObjSectionClass read FCObjSection write FCObjSection;
  355. property CObjSectionGroup: TObjSectionGroupClass read FCObjSectionGroup write FCObjSectionGroup;
  356. public
  357. CurrPass : byte;
  358. ExecStack : boolean;
  359. {$ifdef ARM}
  360. ThumbFunc : boolean;
  361. {$endif ARM}
  362. constructor create(const n:string);virtual;
  363. destructor destroy;override;
  364. { Sections }
  365. function sectionname(atype:TAsmSectiontype;const aname:string;aorder:TAsmSectionOrder):string;virtual;abstract;
  366. class function sectiontype2options(atype:TAsmSectiontype):TObjSectionOptions;virtual;
  367. function sectiontype2align(atype:TAsmSectiontype):longint;virtual;
  368. class procedure sectiontype2progbitsandflags(atype:TAsmSectiontype;out progbits:TSectionProgbits;out flags:TSectionFlags);virtual;
  369. function createsection(atype:TAsmSectionType;const aname:string='';aorder:TAsmSectionOrder=secorder_default):TObjSection;virtual;
  370. function createsection(atype:TAsmSectionType;secflags:TSectionFlags;aprogbits:TSectionProgbits;const aname:string='';aorder:TAsmSectionOrder=secorder_default):TObjSection;virtual;
  371. function createsection(const aname:string;aalign:longint;aoptions:TObjSectionOptions;DiscardDuplicate:boolean=true):TObjSection;virtual;
  372. function createsectiongroup(const aname:string):TObjSectionGroup;
  373. procedure CreateDebugSections;virtual;
  374. function findsection(const aname:string):TObjSection;
  375. procedure setsection(asec:TObjSection);
  376. { Symbols }
  377. function createsymbol(const aname:string):TObjSymbol;
  378. function symboldefine(asmsym:TAsmSymbol):TObjSymbol;
  379. function symboldefine(const aname:string;abind:TAsmsymbind;atyp:Tasmsymtype):TObjSymbol;
  380. function symbolref(asmsym:TAsmSymbol):TObjSymbol;
  381. function symbolref(const aname:string):TObjSymbol;
  382. procedure ResetCachedAsmSymbols;
  383. { Allocation }
  384. procedure alloc(len:aword);
  385. procedure allocalign(len:longint);
  386. procedure writebytes(const Data;len:aword);
  387. procedure writeReloc(Data:TRelocDataInt;len:aword;p:TObjSymbol;Reloctype:TObjRelocationType);virtual;abstract;
  388. procedure beforealloc;virtual;
  389. procedure beforewrite;virtual;
  390. procedure afteralloc;virtual;
  391. procedure afterwrite;virtual;
  392. procedure resetsections;
  393. procedure layoutsections(var datapos:TObjSectionOfs);
  394. property Name:TString80 read FName;
  395. property CurrObjSec:TObjSection read FCurrObjSec;
  396. property ObjSymbolList:TObjSymbolList read FObjSymbolList;
  397. property ObjSectionList:TFPHashObjectList read FObjSectionList;
  398. property GroupsList:TFPHashObjectList read FGroupsList;
  399. property StabsSec:TObjSection read FStabsObjSec write FStabsObjSec;
  400. property StabStrSec:TObjSection read FStabStrObjSec write FStabStrObjSec;
  401. property CObjSymbol: TObjSymbolClass read FCObjSymbol write FCObjSymbol;
  402. { Current CPU type for the internal asm writer.
  403. Instructions, not supported by the given CPU should produce an error.
  404. A value of 'cpu_none' means no restrictions (all instructions should be accepted) }
  405. property CPUType : tcputype read FCPUType write FCPUType;
  406. end;
  407. TObjDataClass = class of TObjData;
  408. TObjOutput = class
  409. private
  410. FCObjData : TObjDataClass;
  411. protected
  412. { writer }
  413. FWriter : TObjectwriter;
  414. function writeData(Data:TObjData):boolean;virtual;abstract;
  415. property CObjData : TObjDataClass read FCObjData write FCObjData;
  416. procedure WriteSectionContent(Data:TObjData);
  417. public
  418. constructor create(AWriter:TObjectWriter);virtual;
  419. destructor destroy;override;
  420. function newObjData(const n:string):TObjData;
  421. function startObjectfile(const fn:string):boolean;
  422. function writeobjectfile(Data:TObjData):boolean;
  423. procedure exportsymbol(p:TObjSymbol);
  424. property Writer:TObjectWriter read FWriter;
  425. end;
  426. TObjOutputClass=class of TObjOutput;
  427. TObjInput = class
  428. private
  429. FCObjData : TObjDataClass;
  430. protected
  431. { reader }
  432. FReader : TObjectReader;
  433. InputFileName : string;
  434. property CObjData : TObjDataClass read FCObjData write FCObjData;
  435. procedure ReadSectionContent(Data:TObjData);
  436. public
  437. constructor create;virtual;
  438. function ReadObjData(AReader:TObjectreader;out Data:TObjData):boolean;virtual;abstract;
  439. class function CanReadObjData(AReader:TObjectreader):boolean;virtual;
  440. procedure inputerror(const s : string);
  441. end;
  442. TObjInputClass=class of TObjInput;
  443. TVTableEntry=record
  444. ObjRelocation : TObjRelocation;
  445. orgreloctype,
  446. orgrelocflags : byte;
  447. Enabled,
  448. Used : Boolean;
  449. end;
  450. PVTableEntry=^TVTableEntry;
  451. TExeVTable = class
  452. private
  453. procedure CheckIdx(VTableIdx:longint);
  454. public
  455. ExeSymbol : TExeSymbol;
  456. EntryCnt : Longint;
  457. EntryArray : PVTableEntry;
  458. Consolidated : Boolean;
  459. ChildList : TFPObjectList;
  460. constructor Create(AExeSymbol:TExeSymbol);
  461. destructor Destroy;override;
  462. procedure AddChild(vt:TExeVTable);
  463. procedure AddEntry(VTableIdx:Longint);
  464. procedure SetVTableSize(ASize:longint);
  465. function VTableRef(VTableIdx:Longint):TObjRelocation;
  466. end;
  467. TSymbolState = (
  468. symstate_undefined,
  469. symstate_undefweak, // undefined but has only weak refs - don't complain
  470. symstate_defined,
  471. symstate_defweak,
  472. symstate_common,
  473. symstate_dynamic // a matching symbol has been seen in .so
  474. );
  475. TExeSymbol = class(TFPHashObject)
  476. ObjSymbol : TObjSymbol;
  477. State : TSymbolState;
  478. used : boolean;
  479. { Used for vmt references optimization }
  480. VTable : TExeVTable;
  481. { fields for ELF linking }
  482. gotoffset : aword;
  483. dynindex : aword;
  484. { A thunk used to redirect some references to symbol (like absolute
  485. jumps/calls to PIC code).
  486. This probably is also needed for ARM/Thumb interworking and alike.
  487. TODO: consider reusing objsymbol.indsymbol for this purpose }
  488. {$ifdef mips}
  489. stubsymbol : TObjSymbol;
  490. {$endif mips}
  491. end;
  492. TExeSection = class(TFPHashObject)
  493. private
  494. FSecSymIdx : longint;
  495. FObjSectionList : TFPObjectList;
  496. public
  497. Size,
  498. DataPos,
  499. MemPos : qword;
  500. SecAlign : longint;
  501. Disabled : boolean;
  502. SecOptions : TObjSectionOptions;
  503. constructor create(AList:TFPHashObjectList;const AName:string);virtual;
  504. destructor destroy;override;
  505. procedure AddObjSection(objsec:TObjSection;ignoreprops:boolean=false);virtual;
  506. { string representation for the linker map file }
  507. function MemPosStr(AImageBase: qword): string;virtual;
  508. property ObjSectionList:TFPObjectList read FObjSectionList;
  509. property SecSymIdx:longint read FSecSymIdx write FSecSymIdx;
  510. end;
  511. TExeSectionClass=class of TExeSection;
  512. TlibKind = (lkArchive,lkObject,lkGroup);
  513. TStaticLibrary = class(TObject)
  514. private
  515. FName : TCmdStr;
  516. FPayload : TObject; { lkArchive: TObjectReader }
  517. { lkObject: TObjData }
  518. { lkGroup: TFPObjectList }
  519. FObjInputClass : TObjInputClass;
  520. FKind: TlibKind;
  521. FAsNeeded : Boolean;
  522. function GetArReader:TObjectReader;
  523. function GetGroupMembers:TFPObjectList;
  524. function GetObjData:TObjData;
  525. public
  526. constructor create(const AName:TCmdStr;AReader:TObjectReader;AObjInputClass:TObjInputClass);
  527. constructor create_object(AObjData:TObjData);
  528. constructor create_group;
  529. destructor destroy;override;
  530. property ArReader:TObjectReader read GetArReader;
  531. property ObjInputClass:TObjInputClass read FObjInputClass;
  532. property GroupMembers:TFPObjectList read GetGroupMembers;
  533. property ObjData:TObjData read GetObjData;
  534. property AsNeeded:Boolean read FAsNeeded write FAsNeeded;
  535. property Kind:TLibKind read FKind;
  536. end;
  537. TImportLibrary = class(TFPHashObject)
  538. private
  539. FImportSymbolList : TFPHashObjectList;
  540. public
  541. constructor create(AList:TFPHashObjectList;const AName:string);
  542. destructor destroy;override;
  543. property ImportSymbolList:TFPHashObjectList read FImportSymbolList;
  544. end;
  545. TImportSymbol = class(TFPHashObject)
  546. private
  547. FOrdNr : longint;
  548. FIsVar : boolean;
  549. FMangledName : string;
  550. FCachedExeSymbol: TExeSymbol;
  551. public
  552. constructor create(AList:TFPHashObjectList;const AName,AMangledName:string;AOrdNr:longint;AIsVar:boolean);
  553. property OrdNr: longint read FOrdNr;
  554. property MangledName: string read FMangledName;
  555. property IsVar: boolean read FIsVar;
  556. property CachedExeSymbol: TExeSymbol read FCachedExeSymbol write FCachedExeSymbol;
  557. end;
  558. TExeWriteMode = (ewm_exefull,ewm_dbgonly,ewm_exeonly);
  559. TExeOutput = class
  560. private
  561. { ExeSectionList }
  562. FCObjSymbol : TObjSymbolClass;
  563. FCObjData : TObjDataClass;
  564. FCExeSection : TExeSectionClass;
  565. FCurrExeSec : TExeSection;
  566. FExeSectionList : TFPHashObjectList;
  567. Fzeronr : longint;
  568. Fvaluesnr : longint;
  569. { Symbols }
  570. FExeSymbolList : TFPHashObjectList;
  571. FUnresolvedExeSymbols : TFPObjectList;
  572. FExternalObjSymbols,
  573. FCommonObjSymbols : TFPObjectList;
  574. FProvidedObjSymbols : TFPObjectList;
  575. FIndirectObjSymbols : TFPObjectList;
  576. FEntryName : string;
  577. FExeVTableList : TFPObjectList;
  578. { Objects }
  579. FObjDataList : TFPObjectList;
  580. { Position calculation }
  581. FImageBase : aword;
  582. FCurrMemPos : qword;
  583. procedure SetCurrMemPos(const AValue: qword);
  584. protected
  585. { writer }
  586. FExeWriteMode : TExeWriteMode;
  587. FWriter : TObjectwriter;
  588. commonObjSection : TObjSection;
  589. internalObjData : TObjData;
  590. EntrySym : TObjSymbol;
  591. SectionDataAlign,
  592. SectionMemAlign : aword;
  593. ComdatGroups : TFPHashList;
  594. FixedSectionAlign : boolean;
  595. AllowUndefinedSymbols : boolean;
  596. function writeData:boolean;virtual;abstract;
  597. property CExeSection:TExeSectionClass read FCExeSection write FCExeSection;
  598. property CObjData:TObjDataClass read FCObjData write FCObjData;
  599. property CObjSymbol:TObjSymbolClass read FCObjSymbol write FCObjSymbol;
  600. procedure Order_ObjSectionList(ObjSectionList : TFPObjectList; const aPattern:string);virtual;
  601. procedure WriteExeSectionContent;
  602. procedure DoRelocationFixup(objsec:TObjSection);virtual;abstract;
  603. function MemAlign(exesec: TExeSection): longword;
  604. function DataAlign(exesec: TExeSection): longword;
  605. procedure ReplaceExeSectionList(newlist: TFPList);
  606. public
  607. CurrDataPos : aword;
  608. MaxMemPos : qword;
  609. IsSharedLibrary : boolean;
  610. ExecStack : boolean;
  611. constructor create;virtual;
  612. destructor destroy;override;
  613. function FindExeSection(const aname:string):TExeSection;
  614. procedure AddObjData(ObjData:TObjData);
  615. procedure Load_Start;virtual;
  616. procedure Load_EntryName(const aname:string);virtual;
  617. procedure Load_Symbol(const aname:string);virtual;
  618. procedure Load_ProvideSymbol(const aname:string);virtual;
  619. procedure Load_IsSharedLibrary;
  620. procedure Load_ImageBase(const avalue:string);
  621. procedure Load_DynamicObject(ObjData:TObjData;asneeded:boolean);virtual;
  622. procedure Order_Start;virtual;
  623. procedure Order_End;virtual;
  624. procedure Order_ExeSection(const aname:string);virtual;
  625. procedure Order_Align(const avalue:string);virtual;
  626. procedure Order_Zeros(const avalue:string);virtual;
  627. procedure Order_Values(bytesize : aword; const avalue:string);virtual;
  628. procedure Order_Symbol(const aname:string);virtual;
  629. procedure Order_ProvideSymbol(const aname:string);virtual;
  630. procedure Order_EndExeSection;virtual;
  631. procedure Order_ObjSection(const aname:string);virtual;
  632. procedure MemPos_Start;virtual;
  633. procedure MemPos_Header;virtual;
  634. procedure MemPos_ExeSection(exesec:TExeSection);
  635. procedure MemPos_ExeSection(const aname:string);virtual;
  636. procedure MemPos_EndExeSection;virtual;
  637. procedure DataPos_Start;virtual;
  638. procedure DataPos_Header;virtual;
  639. procedure DataPos_ExeSection(exesec:TExeSection);
  640. procedure DataPos_ExeSection(const aname:string);virtual;
  641. procedure DataPos_EndExeSection;virtual;
  642. procedure DataPos_Symbols;virtual;
  643. procedure BuildVTableTree(VTInheritList,VTEntryList:TFPObjectList);
  644. procedure PackUnresolvedExeSymbols(const s:string);
  645. procedure ResolveSymbols(StaticLibraryList:TFPObjectList);
  646. procedure PrintMemoryMap;
  647. procedure FixupSymbols;
  648. procedure FixupRelocations;virtual;
  649. procedure RemoveUnusedExeSymbols;
  650. procedure MergeStabs;
  651. procedure MarkEmptySections;
  652. procedure RemoveUnreferencedSections;
  653. procedure RemoveDisabledSections;
  654. procedure RemoveDebugInfo;
  655. procedure MarkTargetSpecificSections(WorkList:TFPObjectList);virtual;
  656. procedure AfterUnusedSectionRemoval;virtual;
  657. procedure GenerateLibraryImports(ImportLibraryList:TFPHashObjectList);virtual;
  658. procedure GenerateDebugLink(const dbgname:string;dbgcrc:cardinal);
  659. function WriteExeFile(const fn:string):boolean;
  660. procedure ParseScript (linkscript:TCmdStrList); virtual;
  661. property Writer:TObjectWriter read FWriter;
  662. property ExeSectionList:TFPHashObjectList read FExeSectionList;
  663. property ObjDataList:TFPObjectList read FObjDataList;
  664. property ExeSymbolList:TFPHashObjectList read FExeSymbolList;
  665. property UnresolvedExeSymbols:TFPObjectList read FUnresolvedExeSymbols;
  666. property ExternalObjSymbols:TFPObjectList read FExternalObjSymbols;
  667. property CommonObjSymbols:TFPObjectList read FCommonObjSymbols;
  668. property IndirectObjSymbols:TFPObjectList read FIndirectObjSymbols;
  669. property ExeVTableList:TFPObjectList read FExeVTableList;
  670. property EntryName:string read FEntryName write FEntryName;
  671. property ImageBase:aword read FImageBase write FImageBase;
  672. property CurrExeSec:TExeSection read FCurrExeSec;
  673. property ExeWriteMode:TExeWriteMode read FExeWriteMode write FExeWriteMode;
  674. property CurrMemPos:qword read FCurrMemPos write SetCurrMemPos;
  675. end;
  676. TExeOutputClass=class of TExeOutput;
  677. const
  678. SectionDataMaxGrow = 4096;
  679. var
  680. exeoutput : TExeOutput;
  681. function align_aword(v:aword;a:longword):aword;
  682. function align_qword(v:qword;a:longword):qword;
  683. function align_objsecofs(v:TObjSectionOfs;a:longword):TObjSectionOfs;
  684. implementation
  685. uses
  686. SysUtils,
  687. globals,verbose,ogmap;
  688. {$ifdef MEMDEBUG}
  689. var
  690. memobjsymbols,
  691. memobjsections : TMemDebug;
  692. {$endif MEMDEBUG}
  693. {*****************************************************************************
  694. Helpers
  695. *****************************************************************************}
  696. function align_aword(v:aword;a:longword):aword;
  697. begin
  698. if a<=1 then
  699. result:=v
  700. else
  701. result:=((v+a-1) div a) * a;
  702. end;
  703. function align_qword(v:qword;a:longword):qword;
  704. begin
  705. if a<=1 then
  706. result:=v
  707. else
  708. result:=((v+a-1) div a) * a;
  709. end;
  710. function align_objsecofs(v:TObjSectionOfs;a:longword):TObjSectionOfs;
  711. begin
  712. if a<=1 then
  713. result:=v
  714. else
  715. result:=((v+a-1) div a) * a;
  716. end;
  717. procedure MaybeSwapStab(var v:TObjStabEntry);
  718. begin
  719. if source_info.endian<>target_info.endian then
  720. begin
  721. v.strpos:=SwapEndian(v.strpos);
  722. v.nvalue:=SwapEndian(v.nvalue);
  723. v.ndesc:=SwapEndian(v.ndesc);
  724. end;
  725. end;
  726. {*****************************************************************************
  727. TObjSymbol
  728. *****************************************************************************}
  729. constructor TObjSymbol.create(AList:TFPHashObjectList;const AName:string);
  730. begin
  731. inherited create(AList,AName);
  732. bind:=AB_EXTERNAL;
  733. typ:=AT_NONE;
  734. symidx:=-1;
  735. size:=0;
  736. offset:=0;
  737. objsection:=nil;
  738. end;
  739. function TObjSymbol.address:qword;
  740. begin
  741. if assigned(objsection) then
  742. result:=offset+objsection.mempos
  743. else
  744. result:=0;
  745. end;
  746. procedure TObjSymbol.SetAddress(apass:byte;aobjsec:TObjSection;abind:TAsmsymbind;atyp:Tasmsymtype);
  747. begin
  748. if not(abind in [AB_GLOBAL,AB_PRIVATE_EXTERN,AB_LOCAL,AB_COMMON,AB_IMPORT]) then
  749. internalerror(200603016);
  750. if not assigned(aobjsec) then
  751. internalerror(200603017);
  752. if (bind in [AB_EXTERNAL,AB_LAZY]) or
  753. { Put all COMMON to GLOBAL in step 3 of
  754. TExeOutput.ResolveSymbols }
  755. ((abind=AB_GLOBAL) and (bind=AB_COMMON)) then
  756. begin
  757. { Do not change the AB_TYPE of common symbols yet }
  758. { This will be done in FixupSymbols }
  759. if (pass<>0) or (bind<>AB_COMMON) then
  760. bind:=abind;
  761. typ:=atyp;
  762. end
  763. else
  764. begin
  765. if pass=apass then
  766. begin
  767. Message1(asmw_e_duplicate_label,name);
  768. exit;
  769. end;
  770. end;
  771. pass:=apass;
  772. { Code can never grow after a pass }
  773. if assigned(objsection) and
  774. (objsection=aobjsec) and
  775. (aobjsec.size>offset) then
  776. internalerror(200603014);
  777. objsection:=aobjsec;
  778. offset:=aobjsec.size;
  779. end;
  780. function TObjSymbol.ObjData: TObjData;
  781. begin
  782. result:=(OwnerList as TObjSymbolList).Owner;
  783. end;
  784. function TObjSymbol.AddressStr(AImageBase: qword): string;
  785. begin
  786. Result:='0x'+HexStr(address+Aimagebase,sizeof(pint)*2);
  787. end;
  788. {****************************************************************************
  789. TObjRelocation
  790. ****************************************************************************}
  791. constructor TObjRelocation.CreateSymbol(ADataOffset:TObjSectionOfs;s:TObjSymbol;Atyp:TObjRelocationType);
  792. begin
  793. if not assigned(s) then
  794. internalerror(200603034);
  795. DataOffset:=ADataOffset;
  796. Symbol:=s;
  797. OrgSize:=0;
  798. Group:=nil;
  799. ObjSection:=nil;
  800. ftype:=ord(Atyp);
  801. end;
  802. constructor TObjRelocation.CreateSection(ADataOffset:TObjSectionOfs;aobjsec:TObjSection;Atyp:TObjRelocationType);
  803. begin
  804. if not assigned(aobjsec) then
  805. internalerror(200603036);
  806. DataOffset:=ADataOffset;
  807. Symbol:=nil;
  808. OrgSize:=0;
  809. Group:=nil;
  810. ObjSection:=aobjsec;
  811. ftype:=ord(Atyp);
  812. end;
  813. constructor TObjRelocation.CreateGroup(ADataOffset:TObjSectionOfs;grp:TObjSectionGroup;Atyp:TObjRelocationType);
  814. begin
  815. if not assigned(grp) then
  816. internalerror(2015111201);
  817. DataOffset:=ADataOffset;
  818. Symbol:=nil;
  819. ObjSection:=nil;
  820. OrgSize:=0;
  821. Group:=grp;
  822. ftype:=ord(Atyp);
  823. end;
  824. constructor TObjRelocation.CreateRaw(ADataOffset:TObjSectionOfs;s:TObjSymbol;ARawType:byte);
  825. begin
  826. { nil symbol is allowed here }
  827. DataOffset:=ADataOffset;
  828. Symbol:=s;
  829. ObjSection:=nil;
  830. Group:=nil;
  831. orgsize:=0;
  832. ftype:=ARawType;
  833. flags:=rf_raw;
  834. end;
  835. function TObjRelocation.GetType:TObjRelocationType;
  836. begin
  837. if (flags and rf_raw)=0 then
  838. result:=TObjRelocationType(ftype)
  839. else
  840. result:=RELOC_RAW;
  841. end;
  842. procedure TObjRelocation.SetType(v:TObjRelocationType);
  843. begin
  844. ftype:=ord(v);
  845. flags:=flags and (not rf_raw);
  846. end;
  847. function TObjRelocation.TargetName:TSymStr;
  848. begin
  849. if assigned(symbol) then
  850. if symbol.typ=AT_SECTION then
  851. result:=symbol.objsection.name
  852. else
  853. result:=symbol.Name
  854. else
  855. result:=objsection.Name;
  856. end;
  857. {****************************************************************************
  858. TObjSection
  859. ****************************************************************************}
  860. constructor TObjSection.create(AList:TFPHashObjectList;const Aname:string;Aalign:longint;Aoptions:TObjSectionOptions);
  861. begin
  862. inherited Create(AList,Aname);
  863. { Data }
  864. Size:=0;
  865. Datapos:=0;
  866. mempos:=0;
  867. FData:=Nil;
  868. {$ifdef i8086}
  869. FSizeLimit:=high(word);
  870. {$else i8086}
  871. FSizeLimit:=high(TObjSectionOfs);
  872. {$endif i8086}
  873. { Setting the secoptions allocates Data if needed }
  874. secoptions:=Aoptions;
  875. secalign:=Aalign;
  876. secsymidx:=0;
  877. { relocation }
  878. ObjRelocations:=TFPObjectList.Create(true);
  879. VTRefList:=TFPObjectList.Create(false);
  880. end;
  881. destructor TObjSection.destroy;
  882. begin
  883. if assigned(Data) then
  884. Data.Free;
  885. stringdispose(FCachedFullName);
  886. ObjRelocations.Free;
  887. VTRefList.Free;
  888. inherited destroy;
  889. end;
  890. procedure TObjSection.SetSecOptions(Aoptions:TObjSectionOptions);
  891. begin
  892. FSecOptions:=FSecOptions+AOptions;
  893. if (oso_Data in secoptions) and
  894. not assigned(FData) then
  895. FData:=TDynamicArray.Create(SectionDataMaxGrow);
  896. end;
  897. procedure TObjSection.SectionTooLargeError;
  898. begin
  899. if oso_executable in SecOptions then
  900. Message(asmw_f_code_segment_too_large)
  901. else
  902. Message(asmw_f_data_segment_too_large);
  903. end;
  904. function TObjSection.write(const d;l:TObjSectionOfs):TObjSectionOfs;
  905. begin
  906. result:=size;
  907. if assigned(Data) then
  908. begin
  909. if Size<>Data.size then
  910. internalerror(200602281);
  911. {$ifndef cpu64bitalu}
  912. if (qword(size)+l)>SizeLimit then
  913. SectionTooLargeError;
  914. {$endif}
  915. Data.write(d,l);
  916. inc(Size,l);
  917. end
  918. else
  919. internalerror(200602289);
  920. end;
  921. function TObjSection.writestr(const s:string):TObjSectionOfs;
  922. var
  923. b: byte;
  924. begin
  925. result:=Write(s[1],length(s));
  926. b:=0;
  927. Write(b,1);
  928. end;
  929. function TObjSection.WriteBytes(const s:string):TObjSectionOfs;
  930. begin
  931. result:=Write(s[1],length(s));
  932. end;
  933. function TObjSection.WriteZeros(l:longword):TObjSectionOfs;
  934. var
  935. empty : array[0..1023] of byte;
  936. begin
  937. result:=Size;
  938. if l>sizeof(empty) then
  939. begin
  940. fillchar(empty,sizeof(empty),0);
  941. while l>sizeof(empty) do
  942. begin
  943. Write(empty,sizeof(empty));
  944. Dec(l,sizeof(empty));
  945. end;
  946. if l>0 then
  947. Write(empty,l);
  948. end
  949. else if l>0 then
  950. begin
  951. fillchar(empty,l,0);
  952. Write(empty,l);
  953. end;
  954. end;
  955. { Writes relocation to (section+offset) without need to have a symbol at that location.
  956. Not an abstract method because not every backend needs this functionality. }
  957. procedure TObjSection.writeReloc_internal(aTarget:TObjSection;offset:aword;len:byte;reltype:TObjRelocationType);
  958. begin
  959. InternalError(2012081501);
  960. end;
  961. procedure TObjSection.setDatapos(var dpos:TObjSectionOfs);
  962. begin
  963. if oso_Data in secoptions then
  964. begin
  965. { get aligned Datapos }
  966. Datapos:=align_aword(dpos,secalign);
  967. Dataalignbytes:=Datapos-dpos;
  968. { return updated Datapos }
  969. dpos:=Datapos+size;
  970. end
  971. else
  972. Datapos:=dpos;
  973. end;
  974. function TObjSection.setmempos(mpos:qword):qword;
  975. begin
  976. mempos:=align_qword(mpos,secalign);
  977. { return updated mempos }
  978. result:=mempos+size;
  979. end;
  980. procedure TObjSection.alloc(l:TObjSectionOfs);
  981. begin
  982. {$ifndef cpu64bitalu}
  983. if (qword(size)+l)>SizeLimit then
  984. SectionTooLargeError;
  985. {$endif}
  986. if oso_sparse_data in SecOptions then
  987. WriteZeros(l)
  988. else
  989. inc(size,l);
  990. end;
  991. procedure TObjSection.addsymReloc(ofs:TObjSectionOfs;p:TObjSymbol;Reloctype:TObjRelocationType);
  992. begin
  993. ObjRelocations.Add(TObjRelocation.CreateSymbol(ofs,p,reloctype));
  994. end;
  995. procedure TObjSection.addsectionReloc(ofs:TObjSectionOfs;aobjsec:TObjSection;Reloctype:TObjRelocationType);
  996. begin
  997. ObjRelocations.Add(TObjRelocation.CreateSection(ofs,aobjsec,reloctype));
  998. end;
  999. procedure TObjSection.addrawReloc(ofs:TObjSectionOfs;p:TObjSymbol;RawReloctype:byte);
  1000. begin
  1001. ObjRelocations.Add(TObjRelocation.CreateRaw(ofs,p,RawReloctype));
  1002. end;
  1003. procedure TObjSection.ReleaseData;
  1004. begin
  1005. if assigned(FData) then
  1006. begin
  1007. FData.free;
  1008. FData:=nil;
  1009. end;
  1010. ObjRelocations.free;
  1011. ObjRelocations:=nil;
  1012. if assigned(FCachedFullName) then
  1013. begin
  1014. stringdispose(FCachedFullName);
  1015. FCachedFullName:=nil;
  1016. end;
  1017. end;
  1018. function TObjSection.FullName:string;
  1019. begin
  1020. if not assigned(FCachedFullName) then
  1021. begin
  1022. if assigned(ObjData) then
  1023. FCachedFullName:=stringdup(ObjData.Name+'('+Name+')')
  1024. else
  1025. FCachedFullName:=stringdup(Name);
  1026. end;
  1027. result:=FCachedFullName^;
  1028. end;
  1029. function TObjSection.MemPosStr(AImageBase: qword): string;
  1030. begin
  1031. result:='0x'+HexStr(mempos+AImageBase,sizeof(pint)*2);
  1032. end;
  1033. {****************************************************************************
  1034. TObjData
  1035. ****************************************************************************}
  1036. constructor TObjData.create(const n:string);
  1037. begin
  1038. inherited create;
  1039. FName:=ExtractFileName(n);
  1040. FObjSectionList:=TFPHashObjectList.Create(true);
  1041. FStabsObjSec:=nil;
  1042. FStabStrObjSec:=nil;
  1043. { symbols }
  1044. FCObjSymbol:=TObjSymbol;
  1045. FObjSymbolList:=TObjSymbolList.Create(true);
  1046. FObjSymbolList.Owner:=Self;
  1047. FCachedAsmSymbolList:=TFPObjectList.Create(false);
  1048. { section class type for creating of new sections }
  1049. FCObjSection:=TObjSection;
  1050. FCObjSectionGroup:=TObjSectionGroup;
  1051. {$ifdef ARM}
  1052. ThumbFunc:=false;
  1053. {$endif ARM}
  1054. end;
  1055. destructor TObjData.destroy;
  1056. begin
  1057. { Symbols }
  1058. {$ifdef MEMDEBUG}
  1059. MemObjSymbols.Start;
  1060. {$endif}
  1061. ResetCachedAsmSymbols;
  1062. FCachedAsmSymbolList.free;
  1063. FObjSymbolList.free;
  1064. {$ifdef MEMDEBUG}
  1065. MemObjSymbols.Stop;
  1066. {$endif}
  1067. GroupsList.free;
  1068. { Sections }
  1069. {$ifdef MEMDEBUG}
  1070. MemObjSections.Start;
  1071. {$endif}
  1072. FObjSectionList.free;
  1073. {$ifdef MEMDEBUG}
  1074. MemObjSections.Stop;
  1075. {$endif}
  1076. inherited destroy;
  1077. end;
  1078. class function TObjData.sectiontype2options(atype:TAsmSectiontype):TObjSectionOptions;
  1079. const
  1080. secoptions : array[TAsmSectiontype] of TObjSectionOptions = ([],
  1081. {user} [oso_Data,oso_load,oso_write],
  1082. {code} [oso_Data,oso_load,oso_executable],
  1083. {Data} [oso_Data,oso_load,oso_write],
  1084. { Readonly data with relocations must be initially writable for some targets.
  1085. Moreover, e.g. for ELF it depends on whether the executable is linked statically or
  1086. dynamically. Here we declare it writable, target-specific descendants must provide
  1087. further handling. }
  1088. {roData} [oso_Data,oso_load,oso_write],
  1089. {roData_norel} [oso_Data,oso_load],
  1090. {bss} [oso_load,oso_write],
  1091. {threadvar} [oso_load,oso_write,oso_threadvar],
  1092. {pdata} [oso_data,oso_load],
  1093. {stub} [oso_Data,oso_load,oso_executable],
  1094. {data_nonlazy} [oso_Data,oso_load,oso_write],
  1095. {data_lazy} [oso_Data,oso_load,oso_write],
  1096. {init_func} [oso_Data,oso_load],
  1097. {term_func} [oso_Data,oso_load],
  1098. {stab} [oso_Data,oso_debug],
  1099. {stabstr} [oso_Data,oso_strings,oso_debug],
  1100. {iData2} [oso_Data,oso_load,oso_write],
  1101. {iData4} [oso_Data,oso_load,oso_write],
  1102. {iData5} [oso_Data,oso_load,oso_write],
  1103. {iData6} [oso_Data,oso_load,oso_write],
  1104. {iData7} [oso_Data,oso_load,oso_write],
  1105. {eData} [oso_Data,oso_load],
  1106. {eh_frame} [oso_Data,oso_load],
  1107. {debug_frame} [oso_Data,oso_debug],
  1108. {debug_info} [oso_Data,oso_debug],
  1109. {debug_line} [oso_Data,oso_debug],
  1110. {debug_abbrev} [oso_Data,oso_debug],
  1111. {debug_aranges} [oso_Data,oso_debug],
  1112. {debug_ranges} [oso_Data,oso_debug],
  1113. {fpc} [oso_Data,oso_load,oso_write],
  1114. {toc} [oso_Data,oso_load],
  1115. {init} [oso_Data,oso_load,oso_executable],
  1116. {fini} [oso_Data,oso_load,oso_executable],
  1117. {objc_class} [oso_data,oso_load],
  1118. {objc_meta_class} [oso_data,oso_load],
  1119. {objc_cat_cls_meth} [oso_data,oso_load],
  1120. {objc_cat_inst_meth} [oso_data,oso_load],
  1121. {objc_protocol} [oso_data,oso_load],
  1122. {objc_string_object} [oso_data,oso_load],
  1123. {objc_cls_meth} [oso_data,oso_load],
  1124. {objc_inst_meth} [oso_data,oso_load],
  1125. {objc_cls_refs} [oso_data,oso_load],
  1126. {objc_message_refs} [oso_data,oso_load],
  1127. {objc_symbols} [oso_data,oso_load],
  1128. {objc_category} [oso_data,oso_load],
  1129. {objc_class_vars} [oso_data,oso_load],
  1130. {objc_instance_vars} [oso_data,oso_load],
  1131. {objc_module_info} [oso_data,oso_load],
  1132. {objc_class_names} [oso_data,oso_load],
  1133. {objc_meth_var_types} [oso_data,oso_load],
  1134. {objc_meth_var_names} [oso_data,oso_load],
  1135. {objc_selector_strs} [oso_data,oso_load],
  1136. {objc_protocol_ext} [oso_data,oso_load],
  1137. {objc_class_ext} [oso_data,oso_load],
  1138. {objc_property} [oso_data,oso_load],
  1139. {objc_image_info} [oso_data,oso_load],
  1140. {objc_cstring_object} [oso_data,oso_load],
  1141. {objc_sel_fixup} [oso_data,oso_load],
  1142. {sec_objc_data} [oso_data,oso_load],
  1143. {sec_objc_const} [oso_data,oso_load],
  1144. {sec_objc_sup_refs} [oso_data,oso_load],
  1145. {sec_data_coalesced} [oso_data,oso_load],
  1146. {sec_objc_classlist} [oso_data,oso_load],
  1147. {sec_objc_nlclasslist} [oso_data,oso_load],
  1148. {sec_objc_catlist} [oso_data,oso_load],
  1149. {sec_objc_nlcatlist} [oso_data,oso_load],
  1150. {sec_objc_protolist'} [oso_data,oso_load],
  1151. {stack} [oso_load,oso_write],
  1152. {heap} [oso_load,oso_write],
  1153. {gcc_except_table} [oso_data,oso_load],
  1154. {arm_attribute} [oso_data]
  1155. );
  1156. begin
  1157. result:=secoptions[atype];
  1158. end;
  1159. function TObjData.sectiontype2align(atype:TAsmSectiontype):longint;
  1160. begin
  1161. case atype of
  1162. sec_stabstr,sec_debug_info,sec_debug_line,sec_debug_abbrev,sec_debug_aranges,sec_debug_ranges,
  1163. sec_arm_attribute:
  1164. result:=1;
  1165. sec_code,
  1166. sec_bss,
  1167. sec_data:
  1168. result:=16;
  1169. { For idata (at least idata2) it must be 4 bytes, because
  1170. an entry is always (also in win64) 20 bytes and aligning
  1171. on 8 bytes will insert 4 bytes between the entries resulting
  1172. in a corrupt idata section.
  1173. Same story with .pdata, it has 4-byte elements which should
  1174. be packed without gaps. }
  1175. sec_idata2,sec_idata4,sec_idata5,sec_idata6,sec_idata7,sec_pdata:
  1176. result:=4;
  1177. else
  1178. result:=sizeof(pint);
  1179. end;
  1180. end;
  1181. class procedure TObjData.sectiontype2progbitsandflags(atype:TAsmSectiontype;out progbits:TSectionProgbits;out flags:TSectionFlags);
  1182. var
  1183. options : TObjSectionOptions;
  1184. begin
  1185. { this is essentially the inverse of the createsection overload that takes
  1186. both progbits and flags as parameters }
  1187. options:=sectiontype2options(atype);
  1188. flags:=[];
  1189. progbits:=SPB_None;
  1190. if oso_load in options then
  1191. include(flags,SF_A);
  1192. if oso_write in options then
  1193. include(flags,SF_W);
  1194. if oso_executable in options then
  1195. include(flags,SF_X);
  1196. if not (oso_data in options) then
  1197. progbits:=SPB_NOBITS
  1198. else if oso_note in options then
  1199. progbits:=SPB_NOTE
  1200. else if oso_arm_attributes in options then
  1201. progbits:=SPB_ARM_ATTRIBUTES;
  1202. end;
  1203. function TObjData.createsection(atype:TAsmSectionType;const aname:string;aorder:TAsmSectionOrder):TObjSection;
  1204. begin
  1205. result:=createsection(sectionname(atype,aname,aorder),sectiontype2align(atype),sectiontype2options(atype));
  1206. end;
  1207. function TObjData.createsection(atype: TAsmSectionType; secflags: TSectionFlags; aprogbits: TSectionProgbits; const aname: string; aorder: TAsmSectionOrder): TObjSection;
  1208. var
  1209. flags : TObjSectionOptions;
  1210. begin
  1211. flags:=[oso_data];
  1212. if SF_A in secflags then
  1213. Include(flags,oso_load);
  1214. if SF_W in secflags then
  1215. Include(flags,oso_write);
  1216. if SF_X in secflags then
  1217. Include(flags,oso_executable);
  1218. if aprogbits=SPB_NOBITS then
  1219. Exclude(flags,oso_data);
  1220. if aprogbits=SPB_NOTE then
  1221. Include(flags,oso_note);
  1222. if aprogbits=SPB_ARM_ATTRIBUTES then
  1223. Include(flags,oso_arm_attributes);
  1224. result:=createsection(sectionname(atype,aname,aorder),sectiontype2align(atype),flags);
  1225. end;
  1226. function TObjData.createsection(const aname:string;aalign:longint;aoptions:TObjSectionOptions;DiscardDuplicate:boolean):TObjSection;
  1227. begin
  1228. if DiscardDuplicate then
  1229. result:=TObjSection(FObjSectionList.Find(aname))
  1230. else
  1231. result:=nil;
  1232. if not assigned(result) then
  1233. begin
  1234. result:=CObjSection.create(FObjSectionList,aname,aalign,aoptions);
  1235. result.ObjData:=self;
  1236. end;
  1237. FCurrObjSec:=result;
  1238. end;
  1239. function TObjData.CreateSectionGroup(const aname:string):TObjSectionGroup;
  1240. begin
  1241. if FGroupsList=nil then
  1242. FGroupsList:=TFPHashObjectList.Create(true);
  1243. result:=CObjSectionGroup.Create(FGroupsList,aname);
  1244. end;
  1245. procedure TObjData.CreateDebugSections;
  1246. begin
  1247. end;
  1248. function TObjData.FindSection(const aname:string):TObjSection;
  1249. begin
  1250. result:=TObjSection(FObjSectionList.Find(aname));
  1251. end;
  1252. procedure TObjData.setsection(asec:TObjSection);
  1253. begin
  1254. if asec.ObjData<>self then
  1255. internalerror(200403041);
  1256. FCurrObjSec:=asec;
  1257. end;
  1258. function TObjData.createsymbol(const aname:string):TObjSymbol;
  1259. begin
  1260. result:=TObjSymbol(FObjSymbolList.Find(aname));
  1261. if not assigned(result) then
  1262. result:=CObjSymbol.Create(FObjSymbolList,aname);
  1263. {$ifdef ARM}
  1264. result.ThumbFunc:=ThumbFunc;
  1265. ThumbFunc:=false;
  1266. {$endif ARM}
  1267. end;
  1268. function TObjData.symboldefine(asmsym:TAsmSymbol):TObjSymbol;
  1269. begin
  1270. if assigned(asmsym) then
  1271. begin
  1272. if asmsym.typ = AT_NONE then
  1273. InternalError(2018062800);
  1274. if not assigned(asmsym.cachedObjSymbol) then
  1275. begin
  1276. result:=symboldefine(asmsym.name,asmsym.bind,asmsym.typ);
  1277. asmsym.cachedObjSymbol:=result;
  1278. FCachedAsmSymbolList.add(asmsym);
  1279. end
  1280. else
  1281. begin
  1282. result:=TObjSymbol(asmsym.cachedObjSymbol);
  1283. result.SetAddress(CurrPass,CurrObjSec,asmsym.bind,asmsym.typ);
  1284. end;
  1285. end
  1286. else
  1287. result:=nil;
  1288. end;
  1289. function TObjData.symboldefine(const aname:string;abind:TAsmsymbind;atyp:Tasmsymtype):TObjSymbol;
  1290. begin
  1291. if not assigned(CurrObjSec) then
  1292. internalerror(200603051);
  1293. result:=CreateSymbol(aname);
  1294. result.SetAddress(CurrPass,CurrObjSec,abind,atyp);
  1295. end;
  1296. function TObjData.symbolref(asmsym:TAsmSymbol):TObjSymbol;
  1297. var
  1298. s:string;
  1299. begin
  1300. if assigned(asmsym) then
  1301. begin
  1302. if not assigned(asmsym.cachedObjSymbol) then
  1303. begin
  1304. s:=asmsym.name;
  1305. result:=TObjSymbol(FObjSymbolList.Find(s));
  1306. if result=nil then
  1307. begin
  1308. result:=CObjSymbol.Create(FObjSymbolList,s);
  1309. if asmsym.bind=AB_WEAK_EXTERNAL then
  1310. result.bind:=AB_WEAK_EXTERNAL;
  1311. end;
  1312. asmsym.cachedObjSymbol:=result;
  1313. FCachedAsmSymbolList.add(asmsym);
  1314. end
  1315. else
  1316. result:=TObjSymbol(asmsym.cachedObjSymbol);
  1317. { The weak bit could have been removed from asmsym. }
  1318. if (asmsym.bind=AB_EXTERNAL) and (result.bind=AB_WEAK_EXTERNAL) then
  1319. result.bind:=AB_EXTERNAL;
  1320. { the TLS type needs to be inherited }
  1321. if asmsym.typ=AT_TLS then
  1322. result.typ:=AT_TLS;
  1323. end
  1324. else
  1325. result:=nil;
  1326. end;
  1327. function TObjData.symbolref(const aname:string):TObjSymbol;
  1328. begin
  1329. if not assigned(CurrObjSec) then
  1330. internalerror(200603052);
  1331. result:=CreateSymbol(aname);
  1332. end;
  1333. procedure TObjData.ResetCachedAsmSymbols;
  1334. var
  1335. i : longint;
  1336. begin
  1337. for i:=0 to FCachedAsmSymbolList.Count-1 do
  1338. tasmsymbol(FCachedAsmSymbolList[i]).cachedObjSymbol:=nil;
  1339. FCachedAsmSymbolList.Clear;
  1340. end;
  1341. procedure TObjData.writebytes(const Data;len:aword);
  1342. begin
  1343. if not assigned(CurrObjSec) then
  1344. internalerror(200402251);
  1345. CurrObjSec.write(Data,len);
  1346. end;
  1347. procedure TObjData.alloc(len:aword);
  1348. begin
  1349. if not assigned(CurrObjSec) then
  1350. internalerror(200402252);
  1351. CurrObjSec.alloc(len);
  1352. end;
  1353. procedure TObjData.allocalign(len:longint);
  1354. begin
  1355. if not assigned(CurrObjSec) then
  1356. internalerror(200402253);
  1357. CurrObjSec.alloc(align_objsecofs(CurrObjSec.size,len)-CurrObjSec.size);
  1358. end;
  1359. procedure TObjData.section_afteralloc(p:TObject;arg:pointer);
  1360. begin
  1361. with TObjSection(p) do
  1362. alloc(align_objsecofs(size,secalign)-size);
  1363. end;
  1364. procedure TObjData.section_afterwrite(p:TObject;arg:pointer);
  1365. begin
  1366. with TObjSection(p) do
  1367. begin
  1368. if assigned(Data) then
  1369. writezeros(align_objsecofs(size,secalign)-size);
  1370. end;
  1371. end;
  1372. procedure TObjData.section_reset(p:TObject;arg:pointer);
  1373. begin
  1374. with TObjSection(p) do
  1375. begin
  1376. Size:=0;
  1377. Datapos:=0;
  1378. mempos:=0;
  1379. if assigned(Data) then
  1380. Data.reset;
  1381. end;
  1382. end;
  1383. procedure TObjData.beforealloc;
  1384. begin
  1385. FCPUType:=current_settings.cputype;
  1386. { create stabs sections if debugging }
  1387. if assigned(StabsSec) then
  1388. begin
  1389. StabsSec.Alloc(sizeof(TObjStabEntry));
  1390. StabStrSec.Alloc(1);
  1391. end;
  1392. end;
  1393. procedure TObjData.beforewrite;
  1394. begin
  1395. FCPUType:=current_settings.cputype;
  1396. { create stabs sections if debugging }
  1397. if assigned(StabsSec) then
  1398. begin
  1399. { Create dummy HdrSym stab, it will be overwritten in AfterWrite }
  1400. StabsSec.WriteZeros(sizeof(TObjStabEntry));
  1401. { start of stabstr }
  1402. StabStrSec.writeZeros(1);
  1403. end;
  1404. end;
  1405. procedure TObjData.afteralloc;
  1406. begin
  1407. FObjSectionList.ForEachCall(@section_afteralloc,nil);
  1408. end;
  1409. procedure TObjData.afterwrite;
  1410. var
  1411. hstab : TObjStabEntry;
  1412. begin
  1413. FObjSectionList.ForEachCall(@section_afterwrite,nil);
  1414. { For the stab section we need an HdrSym which can now be
  1415. calculated more easily }
  1416. if assigned(StabsSec) then
  1417. begin
  1418. { end of stabstr }
  1419. StabStrSec.writeZeros(1);
  1420. { header stab }
  1421. hstab.strpos:=1;
  1422. hstab.ntype:=0;
  1423. hstab.nother:=0;
  1424. {$push}{$R-}
  1425. { for jwawindows.pas, this causes an range check error, it contains too much stab symbols }
  1426. hstab.ndesc:=(StabsSec.Size div sizeof(TObjStabEntry))-1;
  1427. {$pop}
  1428. hstab.nvalue:=StabStrSec.Size;
  1429. MaybeSwapStab(hstab);
  1430. StabsSec.Data.seek(0);
  1431. StabsSec.Data.write(hstab,sizeof(hstab));
  1432. end;
  1433. end;
  1434. procedure TObjData.resetsections;
  1435. begin
  1436. FObjSectionList.ForEachCall(@section_reset,nil);
  1437. end;
  1438. procedure TObjData.layoutsections(var DataPos:TObjSectionOfs);
  1439. var
  1440. i: longint;
  1441. begin
  1442. for i:=0 to FObjSectionList.Count-1 do
  1443. TObjSection(FObjSectionList[i]).setDatapos(DataPos);
  1444. end;
  1445. {****************************************************************************
  1446. TObjOutput
  1447. ****************************************************************************}
  1448. constructor TObjOutput.create(AWriter:TObjectWriter);
  1449. begin
  1450. FWriter:=AWriter;
  1451. CObjData:=TObjData;
  1452. end;
  1453. destructor TObjOutput.destroy;
  1454. begin
  1455. inherited destroy;
  1456. end;
  1457. function TObjOutput.newObjData(const n:string):TObjData;
  1458. begin
  1459. result:=CObjData.create(n);
  1460. if (cs_use_lineinfo in current_settings.globalswitches) or
  1461. (cs_debuginfo in current_settings.moduleswitches) then
  1462. result.CreateDebugSections;
  1463. end;
  1464. function TObjOutput.startObjectfile(const fn:string):boolean;
  1465. begin
  1466. result:=false;
  1467. { start the writer already, so the .a generation can initialize
  1468. the position of the current objectfile }
  1469. if not FWriter.createfile(fn) then
  1470. Comment(V_Fatal,'Can''t create object '+fn);
  1471. result:=true;
  1472. end;
  1473. function TObjOutput.writeobjectfile(Data:TObjData):boolean;
  1474. begin
  1475. if errorcount=0 then
  1476. result:=writeData(Data)
  1477. else
  1478. result:=true;
  1479. { close the writer }
  1480. FWriter.closefile;
  1481. end;
  1482. procedure TObjOutput.exportsymbol(p:TObjSymbol);
  1483. begin
  1484. { export globals and common symbols, this is needed
  1485. for .a files }
  1486. if p.bind in [AB_GLOBAL,AB_PRIVATE_EXTERN,AB_COMMON] then
  1487. FWriter.writesym(p.name);
  1488. end;
  1489. procedure TObjOutput.WriteSectionContent(Data:TObjData);
  1490. var
  1491. i:longint;
  1492. sec:TObjSection;
  1493. begin
  1494. for i:=0 to Data.ObjSectionList.Count-1 do
  1495. begin
  1496. sec:=TObjSection(Data.ObjSectionList[i]);
  1497. if (oso_data in sec.SecOptions) then
  1498. begin
  1499. if sec.Data=nil then
  1500. internalerror(200403073);
  1501. FWriter.writezeros(sec.dataalignbytes);
  1502. if sec.Datapos<>FWriter.ObjSize then
  1503. internalerror(200604031);
  1504. FWriter.writearray(sec.data);
  1505. end;
  1506. end;
  1507. end;
  1508. {****************************************************************************
  1509. TExeVTable
  1510. ****************************************************************************}
  1511. constructor TExeVTable.Create(AExeSymbol:TExeSymbol);
  1512. begin
  1513. ExeSymbol:=AExeSymbol;
  1514. if ExeSymbol.State=symstate_undefined then
  1515. internalerror(200604012);
  1516. ChildList:=TFPObjectList.Create(false);
  1517. end;
  1518. destructor TExeVTable.Destroy;
  1519. begin
  1520. ChildList.Free;
  1521. if assigned(EntryArray) then
  1522. Freemem(EntryArray);
  1523. end;
  1524. procedure TExeVTable.CheckIdx(VTableIdx:longint);
  1525. var
  1526. OldEntryCnt : longint;
  1527. begin
  1528. if VTableIdx>=EntryCnt then
  1529. begin
  1530. OldEntryCnt:=EntryCnt;
  1531. EntryCnt:=VTableIdx+1;
  1532. ReAllocMem(EntryArray,EntryCnt*sizeof(TVTableEntry));
  1533. FillChar(EntryArray[OldEntryCnt],(EntryCnt-OldEntryCnt)*sizeof(TVTableEntry),0);
  1534. end;
  1535. end;
  1536. procedure TExeVTable.AddChild(vt:TExeVTable);
  1537. begin
  1538. ChildList.Add(vt);
  1539. end;
  1540. procedure TExeVTable.AddEntry(VTableIdx:Longint);
  1541. var
  1542. i : longint;
  1543. objreloc : TObjRelocation;
  1544. vtblentryoffset : aword;
  1545. begin
  1546. CheckIdx(VTableIdx);
  1547. vtblentryoffset:=ExeSymbol.ObjSymbol.Offset+longword(VTableIdx)*sizeof(pint);
  1548. { Find and disable relocation }
  1549. for i:=0 to ExeSymbol.ObjSymbol.ObjSection.ObjRelocations.Count-1 do
  1550. begin
  1551. objreloc:=TObjRelocation(ExeSymbol.ObjSymbol.ObjSection.ObjRelocations[i]);
  1552. if objreloc.dataoffset=vtblentryoffset then
  1553. begin
  1554. EntryArray[VTableIdx].ObjRelocation:=objreloc;
  1555. EntryArray[VTableIdx].OrgRelocType:=objreloc.ftype;
  1556. EntryArray[VTableIdx].OrgRelocFlags:=objreloc.flags;
  1557. objreloc.typ:=RELOC_ZERO;
  1558. objreloc.flags:=objreloc.flags or rf_nosymbol;
  1559. break;
  1560. end;
  1561. end;
  1562. if not assigned(EntryArray[VTableIdx].ObjRelocation) then
  1563. internalerror(200604011);
  1564. end;
  1565. procedure TExeVTable.SetVTableSize(ASize:longint);
  1566. begin
  1567. if EntryCnt<>0 then
  1568. internalerror(200603313);
  1569. EntryCnt:=ASize div sizeof(pint);
  1570. EntryArray:=AllocMem(EntryCnt*sizeof(TVTableEntry));
  1571. end;
  1572. function TExeVTable.VTableRef(VTableIdx:Longint):TObjRelocation;
  1573. begin
  1574. result:=nil;
  1575. CheckIdx(VTableIdx);
  1576. if EntryArray[VTableIdx].Used then
  1577. exit;
  1578. { Restore relocation if available }
  1579. if assigned(EntryArray[VTableIdx].ObjRelocation) then
  1580. begin
  1581. EntryArray[VTableIdx].ObjRelocation.ftype:=EntryArray[VTableIdx].OrgRelocType;
  1582. EntryArray[VTableIdx].ObjRelocation.flags:=EntryArray[VTableIdx].OrgRelocFlags;
  1583. result:=EntryArray[VTableIdx].ObjRelocation;
  1584. end;
  1585. EntryArray[VTableIdx].Used:=true;
  1586. end;
  1587. {****************************************************************************
  1588. TExeSection
  1589. ****************************************************************************}
  1590. constructor TExeSection.create(AList:TFPHashObjectList;const AName:string);
  1591. begin
  1592. inherited create(AList,AName);
  1593. Size:=0;
  1594. MemPos:=0;
  1595. DataPos:=0;
  1596. FSecSymIdx:=0;
  1597. FObjSectionList:=TFPObjectList.Create(false);
  1598. end;
  1599. destructor TExeSection.destroy;
  1600. begin
  1601. ObjSectionList.Free;
  1602. inherited destroy;
  1603. end;
  1604. procedure TExeSection.AddObjSection(objsec:TObjSection;ignoreprops:boolean);
  1605. begin
  1606. ObjSectionList.Add(objsec);
  1607. { relate ObjSection to ExeSection, and mark it Used by default }
  1608. objsec.ExeSection:=self;
  1609. objsec.Used:=true;
  1610. if ignoreprops then
  1611. exit;
  1612. if (SecOptions<>[]) then
  1613. begin
  1614. { Only if the section contains (un)initialized data the
  1615. data flag must match. }
  1616. if ((oso_Data in SecOptions)<>(oso_Data in objsec.SecOptions)) then
  1617. Comment(V_Error,'Incompatible section options');
  1618. end
  1619. else
  1620. begin
  1621. { inherit section options }
  1622. SecOptions:=SecOptions+objsec.SecOptions;
  1623. end;
  1624. SecAlign:=max(objsec.SecAlign,SecAlign);
  1625. end;
  1626. function TExeSection.MemPosStr(AImageBase: qword): string;
  1627. begin
  1628. result:='0x'+HexStr(mempos+AImageBase,sizeof(pint)*2);
  1629. end;
  1630. {****************************************************************************
  1631. TStaticLibrary
  1632. ****************************************************************************}
  1633. constructor TStaticLibrary.create(const AName:TCmdStr;AReader:TObjectReader;AObjInputClass:TObjInputClass);
  1634. begin
  1635. FName:=AName;
  1636. FPayload:=AReader;
  1637. FObjInputClass:=AObjInputClass;
  1638. FKind:=lkArchive;
  1639. end;
  1640. constructor TStaticLibrary.create_object(AObjData:TObjData);
  1641. begin
  1642. FPayload:=AObjData;
  1643. FKind:=lkObject;
  1644. end;
  1645. constructor TStaticLibrary.create_group;
  1646. begin
  1647. FPayload:=TFPObjectList.Create(true);
  1648. FKind:=lkGroup;
  1649. end;
  1650. destructor TStaticLibrary.destroy;
  1651. begin
  1652. FPayload.Free;
  1653. inherited destroy;
  1654. end;
  1655. function TStaticLibrary.GetArReader: TObjectReader;
  1656. begin
  1657. if (FKind<>lkArchive) then
  1658. InternalError(2012071501);
  1659. result:=TObjectReader(FPayload);
  1660. end;
  1661. function TStaticLibrary.GetGroupMembers: TFPObjectList;
  1662. begin
  1663. if (FKind<>lkGroup) then
  1664. InternalError(2012071502);
  1665. result:=TFPObjectList(FPayload);
  1666. end;
  1667. function TStaticLibrary.GetObjData: TObjData;
  1668. begin
  1669. if (FKind<>lkObject) then
  1670. InternalError(2012071503);
  1671. result:=TObjData(FPayload);
  1672. end;
  1673. {****************************************************************************
  1674. TImportLibrary
  1675. ****************************************************************************}
  1676. constructor TImportLibrary.create(AList:TFPHashObjectList;const AName:string);
  1677. begin
  1678. inherited create(AList,AName);
  1679. FImportSymbolList:=TFPHashObjectList.Create(true);
  1680. end;
  1681. destructor TImportLibrary.destroy;
  1682. begin
  1683. ImportSymbolList.Free;
  1684. inherited destroy;
  1685. end;
  1686. {****************************************************************************
  1687. TImportSymbol
  1688. ****************************************************************************}
  1689. constructor TImportSymbol.create(AList:TFPHashObjectList;
  1690. const AName,AMangledName:string;AOrdNr:longint;AIsVar:boolean);
  1691. begin
  1692. inherited Create(AList, AName);
  1693. FOrdNr:=AOrdNr;
  1694. FIsVar:=AIsVar;
  1695. FMangledName:=AMangledName;
  1696. { Replace ? and @ in import name, since GNU AS does not allow these characters in symbol names. }
  1697. { This allows to import VC++ mangled names from DLLs. }
  1698. if target_info.system in systems_all_windows then
  1699. begin
  1700. Replace(FMangledName,'?','__q$$');
  1701. {$ifdef arm}
  1702. { @ symbol is not allowed in ARM assembler only }
  1703. Replace(FMangledName,'@','__a$$');
  1704. {$endif arm}
  1705. end;
  1706. end;
  1707. {****************************************************************************
  1708. TExeOutput
  1709. ****************************************************************************}
  1710. constructor TExeOutput.create;
  1711. begin
  1712. { init writer }
  1713. FWriter:=TObjectwriter.create;
  1714. FExeWriteMode:=ewm_exefull;
  1715. { object files }
  1716. FObjDataList:=TFPObjectList.Create(true);
  1717. { symbols }
  1718. FExeSymbolList:=TFPHashObjectList.Create(true);
  1719. FUnresolvedExeSymbols:=TFPObjectList.Create(false);
  1720. FExternalObjSymbols:=TFPObjectList.Create(false);
  1721. FCommonObjSymbols:=TFPObjectList.Create(false);
  1722. FProvidedObjSymbols:=TFPObjectList.Create(false);
  1723. FIndirectObjSymbols:=TFPObjectList.Create(false);
  1724. FExeVTableList:=TFPObjectList.Create(false);
  1725. ComdatGroups:=TFPHashList.Create;
  1726. { sections }
  1727. FExeSectionList:=TFPHashObjectList.Create(true);
  1728. FImageBase:=0;
  1729. {$ifdef cpu16bitaddr}
  1730. SectionMemAlign:=$10;
  1731. SectionDataAlign:=$10;
  1732. {$else cpu16bitaddr}
  1733. SectionMemAlign:=$1000;
  1734. SectionDataAlign:=$200;
  1735. {$endif cpu16bitaddr}
  1736. FixedSectionAlign:=True;
  1737. FCExeSection:=TExeSection;
  1738. FCObjData:=TObjData;
  1739. FCObjSymbol:=TObjSymbol;
  1740. end;
  1741. destructor TExeOutput.destroy;
  1742. begin
  1743. FExeSymbolList.free;
  1744. UnresolvedExeSymbols.free;
  1745. ExternalObjSymbols.free;
  1746. FProvidedObjSymbols.free;
  1747. FIndirectObjSymbols.free;
  1748. CommonObjSymbols.free;
  1749. ExeVTableList.free;
  1750. FExeSectionList.free;
  1751. ComdatGroups.free;
  1752. ObjDatalist.free;
  1753. FWriter.free;
  1754. inherited destroy;
  1755. end;
  1756. function TExeOutput.MemAlign(exesec:TExeSection):longword;
  1757. begin
  1758. if FixedSectionAlign then
  1759. result:=SectionMemAlign
  1760. else
  1761. result:=exesec.SecAlign;
  1762. end;
  1763. function TExeOutput.DataAlign(exesec:TExeSection):longword;
  1764. begin
  1765. if FixedSectionAlign then
  1766. result:=SectionDataAlign
  1767. else
  1768. result:=exesec.SecAlign;
  1769. end;
  1770. function TExeOutput.WriteExeFile(const fn:string):boolean;
  1771. begin
  1772. result:=false;
  1773. if FWriter.createfile(fn) then
  1774. begin
  1775. { Only write the .o if there are no errors }
  1776. if errorcount=0 then
  1777. result:=writedata
  1778. else
  1779. result:=true;
  1780. { close the writer }
  1781. FWriter.closefile;
  1782. end
  1783. else
  1784. Comment(V_Fatal,'Can''t create executable '+fn);
  1785. end;
  1786. procedure TExeOutput.ParseScript (linkscript:TCmdStrList);
  1787. begin
  1788. end;
  1789. function TExeOutput.FindExeSection(const aname:string):TExeSection;
  1790. begin
  1791. result:=TExeSection(ExeSectionList.Find(aname));
  1792. end;
  1793. procedure TExeOutput.AddObjData(ObjData:TObjData);
  1794. begin
  1795. if ObjData.classtype<>FCObjData then
  1796. Comment(V_Error,'Invalid input object format for '+ObjData.name+' got '+ObjData.classname+' expected '+FCObjData.classname);
  1797. ObjDataList.Add(ObjData);
  1798. ExecStack:=ExecStack or ObjData.ExecStack;
  1799. end;
  1800. procedure TExeOutput.Load_Start;
  1801. begin
  1802. ObjDataList.Clear;
  1803. { Globals defined in the linker script }
  1804. if not assigned(internalObjData) then
  1805. internalObjData:=CObjData.create('*Internal*');
  1806. AddObjData(internalObjData);
  1807. { Common Data section }
  1808. commonObjSection:=internalObjData.createsection(sec_bss,'');
  1809. end;
  1810. procedure TExeOutput.Load_EntryName(const aname:string);
  1811. begin
  1812. FEntryName:=aname;
  1813. end;
  1814. procedure TExeOutput.Load_IsSharedLibrary;
  1815. begin
  1816. IsSharedLibrary:=true;
  1817. end;
  1818. procedure TExeOutput.Load_ImageBase(const avalue:string);
  1819. var
  1820. code : integer;
  1821. objsec : TObjSection;
  1822. objsym : TObjSymbol;
  1823. exesym : TExeSymbol;
  1824. begin
  1825. val(avalue,FImageBase,code);
  1826. if code<>0 then
  1827. Comment(V_Error,'Invalid number '+avalue);
  1828. { Create __image_base__ symbol, create the symbol
  1829. in a section with adress 0 and at offset 0 }
  1830. objsec:=internalObjData.createsection('*__image_base__',0,[]);
  1831. internalObjData.setsection(objsec);
  1832. objsym:=internalObjData.SymbolDefine('__image_base__',AB_GLOBAL,AT_DATA);
  1833. exesym:=texesymbol.Create(FExeSymbolList,objsym.name);
  1834. exesym.ObjSymbol:=objsym;
  1835. end;
  1836. procedure TExeOutput.Load_Symbol(const aname:string);
  1837. begin
  1838. internalObjData.createsection('*'+aname,0,[]);
  1839. internalObjData.SymbolDefine(aname,AB_GLOBAL,AT_DATA);
  1840. end;
  1841. procedure TExeOutput.Load_ProvideSymbol(const aname:string);
  1842. begin
  1843. if assigned(ExeSymbolList.Find(aname)) then
  1844. exit;
  1845. internalObjData.createsection('*'+aname,0,[]);
  1846. // Use AB_COMMON to avoid muliple defined complaints
  1847. internalObjData.SymbolDefine(aname,AB_COMMON,AT_DATA);
  1848. end;
  1849. procedure TExeOutput.Load_DynamicObject(ObjData:TObjData;asneeded:boolean);
  1850. begin
  1851. end;
  1852. procedure TExeOutput.Order_Start;
  1853. begin
  1854. end;
  1855. procedure TExeOutput.Order_End;
  1856. begin
  1857. internalObjData.afterwrite;
  1858. end;
  1859. procedure TExeOutput.Order_ExeSection(const aname:string);
  1860. var
  1861. sec : TExeSection;
  1862. begin
  1863. sec:=FindExeSection(aname);
  1864. if not assigned(sec) then
  1865. sec:=CExeSection.create(ExeSectionList,aname);
  1866. { Clear ExeSection contents }
  1867. FCurrExeSec:=sec;
  1868. end;
  1869. procedure TExeOutput.Order_EndExeSection;
  1870. begin
  1871. if not assigned(CurrExeSec) then
  1872. internalerror(200602184);
  1873. FCurrExeSec:=nil;
  1874. end;
  1875. procedure TExeOutput.Order_ObjSection(const aname:string);
  1876. var
  1877. i,j : longint;
  1878. ObjData : TObjData;
  1879. objsec : TObjSection;
  1880. TmpObjSectionList : TFPObjectList;
  1881. begin
  1882. if not assigned(CurrExeSec) then
  1883. internalerror(200602181);
  1884. TmpObjSectionList:=TFPObjectList.Create(false);
  1885. for i:=0 to ObjDataList.Count-1 do
  1886. begin
  1887. ObjData:=TObjData(ObjDataList[i]);
  1888. for j:=0 to ObjData.ObjSectionList.Count-1 do
  1889. begin
  1890. objsec:=TObjSection(ObjData.ObjSectionList[j]);
  1891. if (not objsec.Used) and
  1892. MatchPattern(aname,objsec.name) then
  1893. TmpObjSectionList.Add(objsec);
  1894. end;
  1895. end;
  1896. { Order list if needed }
  1897. Order_ObjSectionList(TmpObjSectionList,aname);
  1898. { Add the (ordered) list to the current ExeSection }
  1899. for i:=0 to TmpObjSectionList.Count-1 do
  1900. begin
  1901. objsec:=TObjSection(TmpObjSectionList[i]);
  1902. CurrExeSec.AddObjSection(objsec);
  1903. end;
  1904. TmpObjSectionList.Free;
  1905. end;
  1906. procedure TExeOutput.Order_ObjSectionList(ObjSectionList : TFPObjectList; const aPattern:string);
  1907. begin
  1908. end;
  1909. procedure TExeOutput.Order_Symbol(const aname:string);
  1910. var
  1911. objsym: TObjSymbol;
  1912. begin
  1913. objsym:=TObjSymbol(internalObjData.ObjSymbolList.Find(aname));
  1914. if (objsym=nil) or (objsym.ObjSection.ObjData<>internalObjData) then
  1915. internalerror(200603041);
  1916. CurrExeSec.AddObjSection(objsym.ObjSection,True);
  1917. end;
  1918. procedure TExeOutput.Order_ProvideSymbol(const aname:string);
  1919. var
  1920. objsym : TObjSymbol;
  1921. exesym : TExeSymbol;
  1922. begin
  1923. objsym:=TObjSymbol(internalObjData.ObjSymbolList.Find(aname));
  1924. if (objsym=nil) or (objsym.ObjSection.ObjData<>internalObjData) then
  1925. internalerror(200603041);
  1926. exesym:=TExeSymbol(ExeSymbolList.Find(aname));
  1927. if not assigned(exesym) then
  1928. internalerror(201206301);
  1929. { Only include this section if it actually resolves
  1930. the symbol }
  1931. if exesym.objsymbol=objsym then
  1932. CurrExeSec.AddObjSection(objsym.ObjSection,True);
  1933. end;
  1934. procedure TExeOutput.Order_Align(const avalue:string);
  1935. var
  1936. code : integer;
  1937. alignval : shortint;
  1938. objsec : TObjSection;
  1939. begin
  1940. val(avalue,alignval,code);
  1941. if code<>0 then
  1942. Comment(V_Error,'Invalid number '+avalue);
  1943. if alignval<=0 then
  1944. exit;
  1945. { Create an empty section with the required aligning }
  1946. inc(Fzeronr);
  1947. objsec:=internalObjData.createsection('*align'+tostr(Fzeronr),alignval,CurrExeSec.SecOptions+[oso_Data,oso_keep]);
  1948. CurrExeSec.AddObjSection(objsec);
  1949. end;
  1950. procedure TExeOutput.Order_Zeros(const avalue:string);
  1951. var
  1952. zeros : array[0..1023] of byte;
  1953. code : integer;
  1954. len : longint;
  1955. objsec : TObjSection;
  1956. begin
  1957. val(avalue,len,code);
  1958. if code<>0 then
  1959. Comment(V_Error,'Invalid number '+avalue);
  1960. if len<=0 then
  1961. exit;
  1962. if len>sizeof(zeros) then
  1963. internalerror(200602254);
  1964. fillchar(zeros,len,0);
  1965. inc(Fzeronr);
  1966. objsec:=internalObjData.createsection('*zeros'+tostr(Fzeronr),0,CurrExeSec.SecOptions+[oso_Data,oso_keep]);
  1967. internalObjData.writebytes(zeros,len);
  1968. CurrExeSec.AddObjSection(objsec);
  1969. end;
  1970. procedure TExeOutput.Order_Values(bytesize : aword; const avalue:string);
  1971. const
  1972. MAXVAL = 128;
  1973. var
  1974. bytevalues : array[0..MAXVAL-1] of byte;
  1975. twobytevalues : array[0..MAXVAL-1] of word;
  1976. fourbytevalues : array[0..MAXVAL-1] of dword;
  1977. eightbytevalues : array[0..MAXVAL-1] of qword;
  1978. allvals, oneval : string;
  1979. len, commapos : longint;
  1980. indexpos, code : integer;
  1981. anumval : qword;
  1982. signedval : int64;
  1983. objsec : TObjSection;
  1984. begin
  1985. indexpos:=0;
  1986. allvals:=avalue;
  1987. { avoid warnings }
  1988. bytevalues[0]:=0;
  1989. twobytevalues[0]:=0;
  1990. fourbytevalues[0]:=0;
  1991. eightbytevalues[0]:=0;
  1992. repeat
  1993. commapos:=pos(',',allvals);
  1994. if commapos>0 then
  1995. begin
  1996. oneval:=trim(copy(allvals,1,commapos-1));
  1997. allvals:=copy(allvals,commapos+1,length(allvals));
  1998. end
  1999. else
  2000. begin
  2001. oneval:=trim(allvals);
  2002. allvals:='';
  2003. end;
  2004. if oneval<>'' then
  2005. begin
  2006. if oneval[1]='-' then
  2007. begin
  2008. val(oneval,signedval,code);
  2009. anumval:=qword(signedval);
  2010. end
  2011. else
  2012. val(oneval,anumval,code);
  2013. if code<>0 then
  2014. Comment(V_Error,'Invalid number '+avalue)
  2015. else
  2016. begin
  2017. if (indexpos<MAXVAL) then
  2018. begin
  2019. if source_info.endian<>target_info.endian then
  2020. swapendian(anumval);
  2021. { No range checking here }
  2022. if bytesize=1 then
  2023. bytevalues[indexpos]:=byte(anumval)
  2024. else if bytesize=2 then
  2025. twobytevalues[indexpos]:=word(anumval)
  2026. else if bytesize=4 then
  2027. fourbytevalues[indexpos]:=dword(anumval)
  2028. else if bytesize=8 then
  2029. eightbytevalues[indexpos]:=anumval;
  2030. inc(indexpos);
  2031. end
  2032. else
  2033. Comment(V_Error,'Buffer overrun in Order_values');
  2034. end;
  2035. end;
  2036. until allvals='';
  2037. if indexpos=0 then
  2038. begin
  2039. Comment(V_Error,'Invalid number '+avalue);
  2040. exit;
  2041. end;
  2042. if indexpos=MAXVAL then
  2043. begin
  2044. Comment(V_Error,'Too many values '+avalue);
  2045. internalerror(200602254);
  2046. end;
  2047. len:=bytesize*indexpos;
  2048. inc(Fvaluesnr);
  2049. objsec:=internalObjData.createsection('*values'+tostr(Fvaluesnr),0,CurrExeSec.SecOptions+[oso_Data,oso_keep]);
  2050. if bytesize=1 then
  2051. internalObjData.writebytes(bytevalues,len)
  2052. else if bytesize=2 then
  2053. internalObjData.writebytes(twobytevalues,len)
  2054. else if bytesize=4 then
  2055. internalObjData.writebytes(fourbytevalues,len)
  2056. else if bytesize=8 then
  2057. internalObjData.writebytes(eightbytevalues,len);
  2058. CurrExeSec.AddObjSection(objsec);
  2059. end;
  2060. procedure TExeOutput.MemPos_Start;
  2061. begin
  2062. CurrMemPos:=0;
  2063. RemoveDisabledSections;
  2064. end;
  2065. procedure TExeOutput.MemPos_Header;
  2066. begin
  2067. end;
  2068. procedure TExeOutput.MemPos_ExeSection(exesec:TExeSection);
  2069. var
  2070. i : longint;
  2071. objsec : TObjSection;
  2072. begin
  2073. { Alignment of ExeSection }
  2074. CurrMemPos:=align_qword(CurrMemPos,MemAlign(exesec));
  2075. exesec.MemPos:=CurrMemPos;
  2076. { set position of object ObjSections }
  2077. for i:=0 to exesec.ObjSectionList.Count-1 do
  2078. begin
  2079. objsec:=TObjSection(exesec.ObjSectionList[i]);
  2080. CurrMemPos:=objsec.setmempos(CurrMemPos);
  2081. end;
  2082. { calculate size of the section }
  2083. exesec.Size:=CurrMemPos-exesec.MemPos;
  2084. end;
  2085. procedure TExeOutput.MemPos_ExeSection(const aname:string);
  2086. begin
  2087. { Section can be removed }
  2088. FCurrExeSec:=FindExeSection(aname);
  2089. if not assigned(CurrExeSec) then
  2090. exit;
  2091. MemPos_ExeSection(CurrExeSec);
  2092. end;
  2093. procedure TExeOutput.MemPos_EndExeSection;
  2094. begin
  2095. if not assigned(CurrExeSec) then
  2096. exit;
  2097. FCurrExeSec:=nil;
  2098. end;
  2099. procedure TExeOutput.DataPos_Start;
  2100. begin
  2101. end;
  2102. procedure TExeOutput.DataPos_Header;
  2103. begin
  2104. end;
  2105. procedure TExeOutput.DataPos_ExeSection(exesec:TExeSection);
  2106. begin
  2107. { don't write normal section if writing only debug info }
  2108. if (ExeWriteMode=ewm_dbgonly) and
  2109. (exesec.SecOptions*[oso_debug,oso_debug_copy]=[]) then
  2110. exit;
  2111. if (oso_Data in exesec.SecOptions) then
  2112. begin
  2113. CurrDataPos:=align_aword(CurrDataPos,DataAlign(exesec));
  2114. exesec.DataPos:=CurrDataPos;
  2115. CurrDataPos:=CurrDataPos+exesec.Size;
  2116. end;
  2117. end;
  2118. procedure TExeOutput.DataPos_ExeSection(const aname:string);
  2119. begin
  2120. { Section can be removed }
  2121. FCurrExeSec:=FindExeSection(aname);
  2122. if not assigned(CurrExeSec) then
  2123. exit;
  2124. DataPos_ExeSection(CurrExeSec);
  2125. end;
  2126. procedure TExeOutput.DataPos_EndExeSection;
  2127. begin
  2128. if not assigned(CurrExeSec) then
  2129. exit;
  2130. FCurrExeSec:=nil;
  2131. end;
  2132. procedure TExeOutput.DataPos_Symbols;
  2133. begin
  2134. end;
  2135. procedure TExeOutput.BuildVTableTree(VTInheritList,VTEntryList:TFPObjectList);
  2136. var
  2137. hs : string;
  2138. code : integer;
  2139. i,k,
  2140. vtableidx : longint;
  2141. vtableexesym,
  2142. childexesym,
  2143. parentexesym : TExeSymbol;
  2144. objsym : TObjSymbol;
  2145. begin
  2146. { Build inheritance tree from VTINHERIT }
  2147. for i:=0 to VTInheritList.Count-1 do
  2148. begin
  2149. objsym:=TObjSymbol(VTInheritList[i]);
  2150. hs:=objsym.name;
  2151. { VTINHERIT_<ChildVMTName>$$<ParentVMTName> }
  2152. Delete(hs,1,Pos('_',hs));
  2153. k:=Pos('$$',hs);
  2154. if k=0 then
  2155. internalerror(200603311);
  2156. childexesym:=texesymbol(FExeSymbolList.Find(Copy(hs,1,k-1)));
  2157. parentexesym:=texesymbol(FExeSymbolList.Find(Copy(hs,k+2,length(hs)-k-1)));
  2158. if not assigned(childexesym) or
  2159. not assigned(parentexesym)then
  2160. internalerror(200603312);
  2161. if not assigned(childexesym.vtable) then
  2162. begin
  2163. childexesym.vtable:=TExeVTable.Create(childexesym);
  2164. ExeVTableList.Add(childexesym.vtable);
  2165. end;
  2166. if not assigned(parentexesym.vtable) then
  2167. begin
  2168. parentexesym.vtable:=TExeVTable.Create(parentexesym);
  2169. ExeVTableList.Add(parentexesym.vtable);
  2170. end;
  2171. childexesym.vtable.SetVTableSize(childexesym.ObjSymbol.Size);
  2172. if parentexesym<>childexesym then
  2173. parentexesym.vtable.AddChild(childexesym.vtable);
  2174. end;
  2175. { Find VTable entries from VTENTRY }
  2176. for i:=0 to VTEntryList.Count-1 do
  2177. begin
  2178. objsym:=TObjSymbol(VTEntryList[i]);
  2179. hs:=objsym.name;
  2180. { VTENTRY_<VTableName>$$<Index> }
  2181. Delete(hs,1,Pos('_',hs));
  2182. k:=Pos('$$',hs);
  2183. if k=0 then
  2184. internalerror(200603319);
  2185. vtableexesym:=texesymbol(FExeSymbolList.Find(Copy(hs,1,k-1)));
  2186. val(Copy(hs,k+2,length(hs)-k-1),vtableidx,code);
  2187. if (code<>0) then
  2188. internalerror(200603318);
  2189. if not assigned(vtableexesym) then
  2190. internalerror(2006033110);
  2191. vtableexesym.vtable.AddEntry(vtableidx);
  2192. end;
  2193. end;
  2194. procedure TExeOutput.PackUnresolvedExeSymbols(const s:string);
  2195. var
  2196. i : longint;
  2197. exesym : TExeSymbol;
  2198. begin
  2199. { Generate a list of Unresolved External symbols }
  2200. for i:=0 to UnresolvedExeSymbols.count-1 do
  2201. begin
  2202. exesym:=TExeSymbol(UnresolvedExeSymbols[i]);
  2203. if not (exesym.State in [symstate_undefined,symstate_undefweak]) then
  2204. UnresolvedExeSymbols[i]:=nil;
  2205. end;
  2206. UnresolvedExeSymbols.Pack;
  2207. Comment(V_Debug,'Number of unresolved externals '+s+' '+tostr(UnresolvedExeSymbols.Count));
  2208. end;
  2209. procedure TExeOutput.ResolveSymbols(StaticLibraryList:TFPObjectList);
  2210. var
  2211. ObjData : TObjData;
  2212. exesym : TExeSymbol;
  2213. objsym,
  2214. commonsym : TObjSymbol;
  2215. firstarchive,
  2216. firstcommon : boolean;
  2217. i : longint;
  2218. VTEntryList,
  2219. VTInheritList : TFPObjectList;
  2220. procedure LoadObjDataSymbols(ObjData:TObjData);
  2221. var
  2222. j : longint;
  2223. hs : string;
  2224. exesym : TExeSymbol;
  2225. tmpsym,
  2226. objsym : TObjSymbol;
  2227. grp : TObjSectionGroup;
  2228. makeexternal : boolean;
  2229. begin
  2230. for j:=0 to ObjData.ObjSymbolList.Count-1 do
  2231. begin
  2232. objsym:=TObjSymbol(ObjData.ObjSymbolList[j]);
  2233. { From the local symbols we are only interessed in the
  2234. VTENTRY and VTINHERIT symbols }
  2235. if objsym.bind=AB_LOCAL then
  2236. begin
  2237. if cs_link_opt_vtable in current_settings.globalswitches then
  2238. begin
  2239. hs:=objsym.name;
  2240. if (hs[1]='V') then
  2241. begin
  2242. if Copy(hs,1,5)='VTREF' then
  2243. begin
  2244. if not assigned(objsym.ObjSection.VTRefList) then
  2245. objsym.ObjSection.VTRefList:=TFPObjectList.Create(false);
  2246. objsym.ObjSection.VTRefList.Add(objsym);
  2247. end
  2248. else if Copy(hs,1,7)='VTENTRY' then
  2249. VTEntryList.Add(objsym)
  2250. else if Copy(hs,1,9)='VTINHERIT' then
  2251. VTInheritList.Add(objsym);
  2252. end;
  2253. end;
  2254. continue;
  2255. end;
  2256. { If this symbol comes from COMDAT group, see if a group with
  2257. matching signature is already included. }
  2258. if assigned(objsym.objsection) and
  2259. assigned(objsym.objsection.group) then
  2260. begin
  2261. grp:=objsym.objsection.group;
  2262. if grp.IsComdat then
  2263. begin
  2264. if ComdatGroups.Find(grp.name)=nil then
  2265. ComdatGroups.Add(grp.name,grp)
  2266. else
  2267. begin
  2268. { Undefine the symbol, causing relocations to it from same
  2269. objdata to be redirected to the symbol in the actually
  2270. linked group. }
  2271. if objsym.bind=AB_GLOBAL then
  2272. objsym.bind:=AB_EXTERNAL;
  2273. { AB_WEAK_EXTERNAL remains unchanged }
  2274. objsym.objsection:=nil;
  2275. end;
  2276. end;
  2277. end;
  2278. { Search for existing exesymbol }
  2279. exesym:=texesymbol(FExeSymbolList.Find(objsym.name));
  2280. if not assigned(exesym) then
  2281. begin
  2282. exesym:=texesymbol.Create(FExeSymbolList,objsym.name);
  2283. exesym.ObjSymbol:=objsym;
  2284. end
  2285. else
  2286. begin
  2287. if assigned(objsym.objsection) and assigned(exesym.objsymbol.objsection) then
  2288. begin
  2289. if (oso_comdat in exesym.ObjSymbol.objsection.SecOptions) and
  2290. (oso_comdat in objsym.objsection.SecOptions) then
  2291. begin
  2292. if exesym.ObjSymbol.objsection.ComdatSelection=objsym.objsection.ComdatSelection then
  2293. begin
  2294. makeexternal:=true;
  2295. case objsym.objsection.ComdatSelection of
  2296. oscs_none:
  2297. makeexternal:=false;
  2298. oscs_any:
  2299. Message1(link_d_comdat_discard_any,objsym.name);
  2300. oscs_same_size:
  2301. if exesym.ObjSymbol.size<>objsym.size then
  2302. Message1(link_e_comdat_size_differs,objsym.name)
  2303. else
  2304. Message1(link_d_comdat_discard_size,objsym.name);
  2305. oscs_exact_match:
  2306. if (exesym.ObjSymbol.size<>objsym.size) and not exesym.ObjSymbol.objsection.Data.equal(objsym.objsection.Data) then
  2307. Message1(link_e_comdat_content_differs,objsym.name)
  2308. else
  2309. Message1(link_d_comdat_discard_content,objsym.name);
  2310. oscs_associative:
  2311. { this is handled in a different way }
  2312. makeexternal:=false;
  2313. oscs_largest:
  2314. if objsym.size>exesym.ObjSymbol.size then
  2315. begin
  2316. Message1(link_d_comdat_replace_size,objsym.name);
  2317. { we swap the symbols and turn the smaller one to an external
  2318. symbol }
  2319. tmpsym:=exesym.objsymbol;
  2320. exesym.objsymbol:=objsym;
  2321. objsym.exesymbol:=exesym;
  2322. objsym:=tmpsym;
  2323. end;
  2324. end;
  2325. if makeexternal then
  2326. begin
  2327. { Undefine the symbol, causing relocations to it from same
  2328. objdata to be redirected to the symbol that is actually
  2329. used }
  2330. if objsym.bind=AB_GLOBAL then
  2331. objsym.bind:=AB_EXTERNAL;
  2332. { AB_WEAK_EXTERNAL remains unchanged }
  2333. objsym.objsection:=nil;
  2334. end;
  2335. end
  2336. else
  2337. Message1(link_e_comdat_selection_differs,objsym.name);
  2338. end;
  2339. end;
  2340. end;
  2341. objsym.ExeSymbol:=exesym;
  2342. case objsym.bind of
  2343. AB_GLOBAL,
  2344. AB_PRIVATE_EXTERN:
  2345. begin
  2346. if exesym.State<>symstate_defined then
  2347. begin
  2348. exesym.ObjSymbol:=objsym;
  2349. exesym.State:=symstate_defined;
  2350. end
  2351. else
  2352. Message1(link_e_duplicate_symbol,objsym.name);
  2353. { hidden symbols must become local symbols in the executable }
  2354. if objsym.bind=AB_PRIVATE_EXTERN then
  2355. objsym.bind:=AB_LOCAL;
  2356. end;
  2357. AB_EXTERNAL :
  2358. begin
  2359. ExternalObjSymbols.add(objsym);
  2360. { Register unresolved symbols only the first time they
  2361. are registered }
  2362. if exesym.ObjSymbol=objsym then
  2363. UnresolvedExeSymbols.Add(exesym)
  2364. { Normal reference removes any existing "weakness" }
  2365. else if exesym.state=symstate_undefweak then
  2366. begin
  2367. exesym.state:=symstate_undefined;
  2368. exesym.ObjSymbol:=objsym;
  2369. end;
  2370. end;
  2371. AB_COMMON :
  2372. begin
  2373. { A COMMON definition overrides weak one.
  2374. Also select the symbol with largest size. }
  2375. if (exesym.State in [symstate_undefined,symstate_undefweak,symstate_defweak]) or
  2376. ((exesym.State=symstate_common) and (objsym.size>exesym.ObjSymbol.size)) then
  2377. begin
  2378. exesym.ObjSymbol:=objsym;
  2379. exesym.State:=symstate_common;
  2380. end;
  2381. if assigned(objsym.objsection) and
  2382. (objsym.objsection.objdata=internalObjData) then
  2383. FProvidedObjSymbols.add(objsym)
  2384. else
  2385. CommonObjSymbols.add(objsym);
  2386. end;
  2387. AB_WEAK_EXTERNAL :
  2388. begin
  2389. if objsym.objsection=nil then { a weak reference }
  2390. begin
  2391. ExternalObjSymbols.add(objsym);
  2392. if exesym.ObjSymbol=objsym then
  2393. begin
  2394. UnresolvedExeSymbols.Add(exesym);
  2395. exesym.state:=symstate_undefweak;
  2396. end;
  2397. end
  2398. else { a weak definition }
  2399. begin
  2400. if exesym.State in [symstate_undefined,symstate_undefweak] then
  2401. begin
  2402. exesym.ObjSymbol:=objsym;
  2403. exesym.state:=symstate_defweak;
  2404. end;
  2405. end;
  2406. end;
  2407. else
  2408. internalerror(2019050510);
  2409. end;
  2410. end;
  2411. end;
  2412. procedure LoadLibrary(lib:TStaticLibrary);
  2413. var
  2414. j,k,oldcount: longint;
  2415. members: TFPObjectList;
  2416. exesym: TExeSymbol;
  2417. objinput: TObjInput;
  2418. begin
  2419. case lib.Kind of
  2420. lkArchive:
  2421. begin
  2422. { Process list of Unresolved External symbols, we need
  2423. to use a while loop because the list can be extended when
  2424. we load members from the library. }
  2425. j:=0;
  2426. while (j<UnresolvedExeSymbols.count) do
  2427. begin
  2428. exesym:=TExeSymbol(UnresolvedExeSymbols[j]);
  2429. { Check first if the symbol is still undefined }
  2430. if (exesym.State=symstate_undefined) then
  2431. begin
  2432. if lib.ArReader.OpenFile(exesym.name) then
  2433. begin
  2434. if assigned(exemap) then
  2435. begin
  2436. if firstarchive then
  2437. begin
  2438. exemap.Add('');
  2439. exemap.Add('Archive member included because of file (symbol)');
  2440. exemap.Add('');
  2441. firstarchive:=false;
  2442. end;
  2443. exemap.Add(lib.ArReader.FileName+' - '+
  2444. {exesym.ObjSymbol.ObjSection.FullName+}
  2445. '('+exesym.Name+')');
  2446. end;
  2447. objinput:=lib.ObjInputClass.Create;
  2448. objinput.ReadObjData(lib.ArReader,objdata);
  2449. objinput.free;
  2450. AddObjData(objdata);
  2451. LoadObjDataSymbols(objdata);
  2452. lib.ArReader.CloseFile;
  2453. end;
  2454. end;
  2455. inc(j);
  2456. end;
  2457. end;
  2458. lkGroup:
  2459. begin
  2460. { repeatedly process members of the group until no new
  2461. unresolved symbols appear }
  2462. members:=lib.GroupMembers;
  2463. repeat
  2464. oldcount:=UnresolvedExeSymbols.count;
  2465. for k:=0 to members.Count-1 do
  2466. LoadLibrary(TStaticLibrary(members[k]));
  2467. until UnresolvedExeSymbols.count=oldcount;
  2468. end;
  2469. lkObject:
  2470. { TODO: ownership of objdata }
  2471. //if lib.objdata.is_dynamic then
  2472. Load_DynamicObject(lib.objdata,lib.AsNeeded);
  2473. {else
  2474. begin
  2475. AddObjData(lib.objdata);
  2476. LoadObjDataSymbols(lib.objdata);
  2477. end;}
  2478. end;
  2479. end;
  2480. begin
  2481. VTEntryList:=TFPObjectList.Create(false);
  2482. VTInheritList:=TFPObjectList.Create(false);
  2483. {
  2484. The symbol resolving is done in 4 steps:
  2485. 1. Register symbols from objects
  2486. 2. Find symbols in static libraries
  2487. 3. Define symbols PROVIDEd by the link script
  2488. 4. Define still undefined common symbols
  2489. }
  2490. { Step 1, Register symbols from objects }
  2491. for i:=0 to ObjDataList.Count-1 do
  2492. begin
  2493. ObjData:=TObjData(ObjDataList[i]);
  2494. LoadObjDataSymbols(ObjData);
  2495. end;
  2496. PackUnresolvedExeSymbols('in objects');
  2497. { Step 2, Find unresolved symbols in the libraries }
  2498. firstarchive:=true;
  2499. for i:=0 to StaticLibraryList.Count-1 do
  2500. LoadLibrary(TStaticLibrary(StaticLibraryList[i]));
  2501. PackUnresolvedExeSymbols('after static libraries');
  2502. { Step 3, handle symbols provided in script }
  2503. for i:=0 to FProvidedObjSymbols.count-1 do
  2504. begin
  2505. objsym:=TObjSymbol(FProvidedObjSymbols[i]);
  2506. if objsym.exesymbol.State=symstate_defined then
  2507. continue;
  2508. objsym.exesymbol.objsymbol:=objsym;
  2509. objsym.bind:=AB_GLOBAL;
  2510. objsym.exesymbol.State:=symstate_defined;
  2511. end;
  2512. PackUnresolvedExeSymbols('after defining symbols provided by link script');
  2513. { Step 4, Match common symbols or add to the globals }
  2514. firstcommon:=true;
  2515. for i:=0 to CommonObjSymbols.count-1 do
  2516. begin
  2517. objsym:=TObjSymbol(CommonObjSymbols[i]);
  2518. if objsym.exesymbol.State=symstate_defined then
  2519. begin
  2520. if objsym.exesymbol.ObjSymbol.size<>objsym.size then
  2521. Comment(V_Debug,'Size of common symbol '+objsym.name+' is different, expected '+tostr(objsym.size)+' got '+tostr(objsym.exesymbol.ObjSymbol.size));
  2522. end
  2523. else
  2524. begin
  2525. { allocate new objsymbol in .bss of *COMMON* and assign
  2526. it to the exesymbol }
  2527. if firstcommon then
  2528. begin
  2529. if assigned(exemap) then
  2530. exemap.AddCommonSymbolsHeader;
  2531. firstcommon:=false;
  2532. end;
  2533. internalObjData.setsection(commonObjSection);
  2534. { TODO: support alignment of common symbols (ELF targets at least),
  2535. increase commonObjSection.SecAlign if necessary here. }
  2536. internalObjData.allocalign(used_align(size_2_align(objsym.size),0,commonObjSection.SecAlign));
  2537. commonsym:=internalObjData.symboldefine(objsym.name,AB_GLOBAL,AT_DATA);
  2538. commonsym.size:=objsym.size;
  2539. internalObjData.alloc(objsym.size);
  2540. if assigned(exemap) then
  2541. exemap.AddCommonSymbol(objsym);
  2542. { Assign to the exesymbol }
  2543. objsym.exesymbol.objsymbol:=commonsym;
  2544. objsym.exesymbol.state:=symstate_defined;
  2545. end;
  2546. end;
  2547. PackUnresolvedExeSymbols('after defining COMMON symbols');
  2548. { Find entry symbol and print in map }
  2549. if (EntryName<>'') then
  2550. begin
  2551. exesym:=texesymbol(ExeSymbolList.Find(EntryName));
  2552. if assigned(exesym) then
  2553. begin
  2554. EntrySym:=exesym.ObjSymbol;
  2555. if assigned(exemap) then
  2556. begin
  2557. exemap.Add('');
  2558. exemap.Add('Entry symbol '+EntryName);
  2559. end;
  2560. end
  2561. else
  2562. Comment(V_Error,'Entrypoint '+EntryName+' not defined');
  2563. end;
  2564. { Generate VTable tree }
  2565. if cs_link_opt_vtable in current_settings.globalswitches then
  2566. BuildVTableTree(VTInheritList,VTEntryList);
  2567. VTInheritList.Free;
  2568. VTEntryList.Free;
  2569. end;
  2570. procedure TExeOutput.GenerateDebugLink(const dbgname:string;dbgcrc:cardinal);
  2571. var
  2572. debuglink : array[0..1023] of byte;
  2573. len : longint;
  2574. objsec : TObjSection;
  2575. exesec : TExeSection;
  2576. begin
  2577. { From the gdb manual chapter 15. GDB Files:
  2578. * A filename, with any leading directory components removed, followed by a zero byte,
  2579. * zero to three bytes of padding, as needed to reach the next four-byte boundary within the section, and
  2580. * a four-byte CRC checksum, stored in the same endianness used for the executable file itself. The checksum is computed
  2581. on the debugging information file's full contents by the function given below, passing zero as the crc argument.
  2582. }
  2583. fillchar(debuglink,sizeof(debuglink),0);
  2584. len:=0;
  2585. move(dbgname[1],debuglink[len],length(dbgname));
  2586. inc(len,length(dbgname)+1);
  2587. len:=align(len,4);
  2588. if source_info.endian<>target_info.endian then
  2589. SwapEndian(dbgcrc);
  2590. move(dbgcrc,debuglink[len],sizeof(cardinal));
  2591. inc(len,4);
  2592. { Add section }
  2593. exesec:=FindExeSection(debuglinkname);
  2594. if not assigned(exesec) then
  2595. exesec:=CExeSection.create(ExeSectionList,debuglinkname);
  2596. exesec.SecOptions:=[oso_data,oso_keep];
  2597. exesec.SecAlign:=4;
  2598. objsec:=internalObjData.createsection(exesec.name,1,exesec.SecOptions);
  2599. internalObjData.writebytes(debuglink,len);
  2600. exesec.AddObjSection(objsec);
  2601. end;
  2602. procedure TExeOutput.GenerateLibraryImports(ImportLibraryList:TFPHashObjectList);
  2603. begin
  2604. end;
  2605. procedure TExeOutput.MarkTargetSpecificSections(WorkList:TFPObjectList);
  2606. begin
  2607. end;
  2608. procedure TExeOutput.AfterUnusedSectionRemoval;
  2609. begin
  2610. end;
  2611. function ByAddress(item1,item2:pointer):longint;
  2612. var
  2613. sym1:TObjSymbol absolute item1;
  2614. sym2:TObjSymbol absolute item2;
  2615. begin
  2616. if sym1.address>sym2.address then
  2617. result:=1
  2618. else if sym1.address<sym2.address then
  2619. result:=-1
  2620. else
  2621. result:=0;
  2622. end;
  2623. procedure TExeOutput.PrintMemoryMap;
  2624. var
  2625. exesec : TExeSection;
  2626. objsec : TObjSection;
  2627. objsym : TObjSymbol;
  2628. i,j,k,m: longint;
  2629. list : TFPList;
  2630. flag : boolean;
  2631. begin
  2632. if not assigned(exemap) then
  2633. exit;
  2634. { create a list of symbols sorted by address }
  2635. list:=TFPList.Create;
  2636. for i:=0 to ExeSymbolList.Count-1 do
  2637. list.Add(TExeSymbol(ExeSymbolList[i]).ObjSymbol);
  2638. list.Sort(@ByAddress);
  2639. exemap.AddMemoryMapHeader(ImageBase);
  2640. k:=0;
  2641. for i:=0 to ExeSectionList.Count-1 do
  2642. begin
  2643. exesec:=TExeSection(ExeSectionList[i]);
  2644. exemap.AddMemoryMapExeSection(exesec);
  2645. for j:=0 to exesec.ObjSectionList.count-1 do
  2646. begin
  2647. objsec:=TObjSection(exesec.ObjSectionList[j]);
  2648. exemap.AddMemoryMapObjectSection(objsec);
  2649. while (k<list.Count) and (TObjSymbol(list[k]).Address<objsec.MemPos) do
  2650. inc(k);
  2651. while (k<list.Count) do
  2652. begin
  2653. objsym:=TObjSymbol(list[k]);
  2654. if objsym.address>objsec.MemPos+objsec.Size then
  2655. break;
  2656. if objsym.objsection=objsec then
  2657. exemap.AddMemoryMapSymbol(objsym)
  2658. else
  2659. begin
  2660. { Got a symbol with address falling into current section, but
  2661. belonging to a different section. This may happen for zero-length
  2662. sections because symbol list is sorted by address but not by section.
  2663. Do some look-ahead in this case. }
  2664. m:=k+1;
  2665. flag:=false;
  2666. while (m<list.Count) and (TObjSymbol(list[m]).Address=objsym.address) do
  2667. begin
  2668. if TObjSymbol(list[m]).objsection=objsec then
  2669. begin
  2670. flag:=true;
  2671. list.Exchange(k,m);
  2672. exemap.AddMemoryMapSymbol(TObjSymbol(list[k]));
  2673. break;
  2674. end;
  2675. inc(m);
  2676. end;
  2677. if not flag then
  2678. break;
  2679. end;
  2680. inc(k);
  2681. end;
  2682. end;
  2683. end;
  2684. list.Free;
  2685. end;
  2686. procedure TExeOutput.FixupSymbols;
  2687. procedure UpdateSymbol(objsym:TObjSymbol);
  2688. begin
  2689. objsym.bind:=objsym.ExeSymbol.ObjSymbol.bind;
  2690. objsym.offset:=objsym.ExeSymbol.ObjSymbol.offset;
  2691. objsym.size:=objsym.ExeSymbol.ObjSymbol.size;
  2692. objsym.typ:=objsym.ExeSymbol.ObjSymbol.typ;
  2693. objsym.ObjSection:=objsym.ExeSymbol.ObjSymbol.ObjSection;
  2694. objsym.group:=objsym.ExeSymbol.ObjSymbol.group;
  2695. end;
  2696. var
  2697. i : longint;
  2698. objsym : TObjSymbol;
  2699. exesym : TExeSymbol;
  2700. begin
  2701. { Print list of Unresolved External symbols }
  2702. if not AllowUndefinedSymbols then
  2703. for i:=0 to UnresolvedExeSymbols.count-1 do
  2704. begin
  2705. exesym:=TExeSymbol(UnresolvedExeSymbols[i]);
  2706. if (exesym.State=symstate_undefined) then
  2707. begin
  2708. if assigned(exesym.ObjSymbol) and assigned(exesym.ObjSymbol.ObjData) then
  2709. Message2(link_e_undefined_symbol_in_obj,exesym.name,exesym.objsymbol.ObjData.Name)
  2710. else
  2711. Message1(link_e_undefined_symbol,exesym.name);
  2712. end;
  2713. end;
  2714. {
  2715. Fixing up symbols is done in the following steps:
  2716. 1. Update common references
  2717. 2. Update external references
  2718. Symbols with objsection<>nil are removed from the lists,
  2719. remaining ones can be processed later by calling this method again.
  2720. }
  2721. { Step 1, Update commons. Preserve the original symbol size and bind,
  2722. this is needed for correct relocation of DJCOFF files. }
  2723. for i:=0 to CommonObjSymbols.count-1 do
  2724. begin
  2725. objsym:=TObjSymbol(CommonObjSymbols[i]);
  2726. if objsym.bind<>AB_COMMON then
  2727. internalerror(200606241);
  2728. objsym.ObjSection:=objsym.ExeSymbol.ObjSymbol.ObjSection;
  2729. objsym.offset:=objsym.ExeSymbol.ObjSymbol.offset;
  2730. objsym.typ:=objsym.ExeSymbol.ObjSymbol.typ;
  2731. end;
  2732. { Step 2, Update externals }
  2733. for i:=0 to ExternalObjSymbols.count-1 do
  2734. begin
  2735. objsym:=TObjSymbol(ExternalObjSymbols[i]);
  2736. if not (objsym.bind in [AB_EXTERNAL,AB_WEAK_EXTERNAL]) then
  2737. internalerror(200606242);
  2738. UpdateSymbol(objsym);
  2739. { Collect symbols that resolve to indirect functions,
  2740. they will need additional target-specific processing. }
  2741. if objsym.typ=AT_GNU_IFUNC then
  2742. IndirectObjSymbols.Add(objsym)
  2743. else if assigned(objsym.objsection) then
  2744. ExternalObjSymbols[i]:=nil;
  2745. end;
  2746. CommonObjSymbols.Clear;
  2747. ExternalObjSymbols.Pack;
  2748. end;
  2749. procedure TExeOutput.MergeStabs;
  2750. var
  2751. stabexesec,
  2752. stabstrexesec : TExeSection;
  2753. relocsec,
  2754. currstabsec,
  2755. currstabstrsec,
  2756. mergedstabsec,
  2757. mergedstabstrsec : TObjSection;
  2758. hstabreloc,
  2759. currstabreloc : TObjRelocation;
  2760. i,j : longint;
  2761. currstabrelocidx,
  2762. mergestabcnt,
  2763. stabcnt : longword;
  2764. skipstab : boolean;
  2765. skipfun : boolean;
  2766. hstab : TObjStabEntry;
  2767. stabrelocofs : longword;
  2768. buf : array[0..1023] of byte;
  2769. bufend,
  2770. bufsize : longint;
  2771. begin
  2772. stabexesec:=FindExeSection('.stab');
  2773. stabstrexesec:=FindExeSection('.stabstr');
  2774. if (stabexesec=nil) or
  2775. (stabstrexesec=nil) or
  2776. (stabexesec.ObjSectionlist.count=0) then
  2777. exit;
  2778. { Create new stabsection }
  2779. stabRelocofs:=pbyte(@hstab.nvalue)-pbyte(@hstab);
  2780. mergedstabsec:=internalObjData.CreateSection(sec_stab,'');
  2781. mergedstabstrsec:=internalObjData.CreateSection(sec_stabstr,'');
  2782. { write stab for hdrsym }
  2783. mergedstabsec.writeZeros(sizeof(TObjStabEntry));
  2784. mergestabcnt:=1;
  2785. { .stabstr starts with a #0 }
  2786. buf[0]:=0;
  2787. mergedstabstrsec.write(buf[0],1);
  2788. skipfun:=false;
  2789. { Copy stabs and corresponding Relocations }
  2790. for i:=0 to stabexesec.ObjSectionList.Count-1 do
  2791. begin
  2792. currstabsec:=TObjSection(stabexesec.ObjSectionList[i]);
  2793. currstabstrsec:=currstabsec.ObjData.findsection('.stabstr');
  2794. if assigned(currstabstrsec) then
  2795. begin
  2796. stabcnt:=currstabsec.Data.size div sizeof(TObjStabEntry);
  2797. currstabsec.Data.seek(0);
  2798. currstabrelocidx:=0;
  2799. for j:=0 to stabcnt-1 do
  2800. begin
  2801. hstabreloc:=nil;
  2802. skipstab:=false;
  2803. currstabsec.Data.read(hstab,sizeof(TObjStabEntry));
  2804. MaybeSwapStab(hstab);
  2805. { Only include first hdrsym stab }
  2806. if hstab.ntype=0 then
  2807. skipstab:=true;
  2808. if skipfun then
  2809. begin
  2810. { Skip all stabs for function body until N_RBRAC }
  2811. skipfun:=hstab.ntype<>N_RBRAC;
  2812. skipstab:=true;
  2813. end;
  2814. if not skipstab then
  2815. begin
  2816. { Find corresponding Relocation }
  2817. currstabreloc:=nil;
  2818. while (currstabrelocidx<longword(currstabsec.ObjRelocations.Count)) do
  2819. begin
  2820. currstabreloc:=TObjRelocation(currstabsec.ObjRelocations[currstabrelocidx]);
  2821. if assigned(currstabreloc) and
  2822. (currstabreloc.dataoffset>=longword(j)*sizeof(TObjStabEntry)+stabrelocofs) then
  2823. break;
  2824. inc(currstabrelocidx);
  2825. end;
  2826. if assigned(currstabreloc) and
  2827. (currstabreloc.dataoffset=longword(j)*sizeof(TObjStabEntry)+stabrelocofs) then
  2828. begin
  2829. hstabReloc:=currstabReloc;
  2830. inc(currstabrelocidx);
  2831. end;
  2832. { Check if the stab is refering to a removed section }
  2833. if assigned(hstabreloc) then
  2834. begin
  2835. if assigned(hstabreloc.Symbol) then
  2836. relocsec:=hstabreloc.Symbol.ObjSection
  2837. else
  2838. relocsec:=hstabreloc.ObjSection;
  2839. if not assigned(relocsec) then
  2840. internalerror(200603302);
  2841. if not relocsec.Used then
  2842. begin
  2843. skipstab:=true;
  2844. if (hstab.ntype=N_Function) and (hstab.strpos<>0) then
  2845. begin
  2846. currstabstrsec.Data.seek(hstab.strpos);
  2847. bufsize:=currstabstrsec.Data.read(buf,sizeof(buf));
  2848. bufend:=indexbyte(buf,bufsize,Ord(':'));
  2849. if (bufend<>-1) and (bufend<bufsize-1) and (buf[bufend+1]=Ord('F')) then
  2850. skipfun:=true;
  2851. end;
  2852. end;
  2853. end;
  2854. end;
  2855. if not skipstab then
  2856. begin
  2857. { Copy string in stabstr }
  2858. if hstab.strpos<>0 then
  2859. begin
  2860. currstabstrsec.Data.seek(hstab.strpos);
  2861. hstab.strpos:=mergedstabstrsec.Size;
  2862. repeat
  2863. bufsize:=currstabstrsec.Data.read(buf,sizeof(buf));
  2864. bufend:=indexbyte(buf,bufsize,0);
  2865. if bufend=-1 then
  2866. bufend:=bufsize
  2867. else
  2868. begin
  2869. { include the #0 }
  2870. inc(bufend);
  2871. end;
  2872. mergedstabstrsec.write(buf,bufend);
  2873. until (buf[bufend-1]=0) or (bufsize<sizeof(buf));
  2874. end;
  2875. { Copy and Update the relocation }
  2876. if assigned(hstabreloc) then
  2877. begin
  2878. hstabreloc.Dataoffset:=mergestabcnt*sizeof(TObjStabEntry)+stabRelocofs;
  2879. { Remove from List without freeing the object }
  2880. currstabsec.ObjRelocations.List[currstabrelocidx-1]:=nil;
  2881. mergedstabsec.ObjRelocations.Add(hstabreloc);
  2882. end;
  2883. { Write updated stab }
  2884. MaybeSwapStab(hstab);
  2885. mergedstabsec.write(hstab,sizeof(hstab));
  2886. inc(mergestabcnt);
  2887. end;
  2888. end;
  2889. end;
  2890. { Unload stabs }
  2891. if assigned(currstabstrsec) then
  2892. begin
  2893. currstabstrsec.Used:=False;
  2894. currstabstrsec.ReleaseData;
  2895. end;
  2896. currstabsec.Used:=false;
  2897. currstabsec.ReleaseData;
  2898. end;
  2899. { Generate new HdrSym }
  2900. if mergedstabsec.Size>0 then
  2901. begin
  2902. hstab.strpos:=1;
  2903. hstab.ntype:=0;
  2904. hstab.nother:=0;
  2905. hstab.ndesc:=word(mergestabcnt-1);
  2906. hstab.nvalue:=mergedstabstrsec.Size;
  2907. MaybeSwapStab(hstab);
  2908. mergedstabsec.Data.seek(0);
  2909. mergedstabsec.Data.write(hstab,sizeof(hstab));
  2910. end;
  2911. { Replace all sections with our combined stabsec }
  2912. stabexesec.ObjSectionList.Clear;
  2913. stabstrexesec.ObjSectionList.Clear;
  2914. stabexesec.AddObjSection(mergedstabsec);
  2915. stabstrexesec.AddObjSection(mergedstabstrsec);
  2916. end;
  2917. procedure TExeOutput.MarkEmptySections;
  2918. var
  2919. i, j : longint;
  2920. exesec : TExeSection;
  2921. doremove : boolean;
  2922. begin
  2923. for i:=0 to ExeSectionList.Count-1 do
  2924. begin
  2925. exesec:=TExeSection(ExeSectionList[i]);
  2926. doremove:=not(oso_keep in exesec.SecOptions) and
  2927. (
  2928. (exesec.ObjSectionlist.count=0) or
  2929. (
  2930. (cs_link_strip in current_settings.globalswitches) and
  2931. not(cs_link_separate_dbg_file in current_settings.globalswitches) and
  2932. (oso_debug in exesec.SecOptions)
  2933. )
  2934. );
  2935. if not doremove then
  2936. begin
  2937. { Check if section has no actual data }
  2938. doremove:=true;
  2939. for j:=0 to exesec.ObjSectionList.Count-1 do
  2940. if TObjSection(exesec.ObjSectionList[j]).Size<>0 then
  2941. begin
  2942. doremove:=false;
  2943. break;
  2944. end;
  2945. end;
  2946. if doremove then
  2947. begin
  2948. Comment(V_Debug,'Disabling empty section '+exesec.name);
  2949. exesec.Disabled:=true;
  2950. end;
  2951. end;
  2952. end;
  2953. procedure TExeOutput.RemoveDisabledSections;
  2954. var
  2955. i: longint;
  2956. exesec: TExeSection;
  2957. begin
  2958. for i:=0 to ExeSectionList.Count-1 do
  2959. begin
  2960. exesec:=TExeSection(ExeSectionList[i]);
  2961. if exesec.Disabled then
  2962. ExeSectionList[i]:=nil;
  2963. end;
  2964. ExeSectionList.Pack;
  2965. end;
  2966. procedure TExeOutput.RemoveDebugInfo;
  2967. var
  2968. i : longint;
  2969. exesec : TExeSection;
  2970. begin
  2971. for i:=0 to ExeSectionList.Count-1 do
  2972. begin
  2973. exesec:=TExeSection(ExeSectionList[i]);
  2974. if (oso_debug in exesec.SecOptions) then
  2975. ExeSectionList[i]:=nil;
  2976. end;
  2977. ExeSectionList.Pack;
  2978. end;
  2979. procedure TExeOutput.RemoveUnreferencedSections;
  2980. var
  2981. ObjSectionWorkList : TFPObjectList;
  2982. procedure AddToObjSectionWorkList(aobjsec:TObjSection);
  2983. begin
  2984. if not aobjsec.Used then
  2985. begin
  2986. aobjsec.Used:=true;
  2987. ObjSectionWorkList.Add(aobjsec);
  2988. end;
  2989. end;
  2990. procedure DoReloc(objreloc:TObjRelocation);
  2991. var
  2992. objsym : TObjSymbol;
  2993. refobjsec : TObjSection;
  2994. refgrp : TObjSectionGroup;
  2995. begin
  2996. { Disabled Relocation to 0 }
  2997. if (objreloc.flags and rf_nosymbol)<>0 then
  2998. exit;
  2999. refobjsec:=nil;
  3000. refgrp:=nil;
  3001. if assigned(objreloc.symbol) then
  3002. begin
  3003. objsym:=objreloc.symbol;
  3004. if objsym.bind<>AB_LOCAL then
  3005. begin
  3006. if not assigned(objsym.exesymbol) then
  3007. internalerror(200603063);
  3008. objsym.exesymbol.used:=true;
  3009. objsym:=objsym.exesymbol.objsymbol;
  3010. end;
  3011. if not assigned(objsym.objsection) then
  3012. exit
  3013. else
  3014. refobjsec:=objsym.objsection;
  3015. end
  3016. else if assigned(objreloc.objsection) then
  3017. refobjsec:=objreloc.objsection
  3018. else if assigned(objreloc.group) then
  3019. refgrp:=objreloc.group
  3020. else
  3021. internalerror(200603316);
  3022. if assigned(exemap) then
  3023. begin
  3024. objsym:=objreloc.symbol;
  3025. if assigned(objsym) and (objsym.typ<>AT_SECTION) then
  3026. exemap.Add(' References '+objsym.name+' in '
  3027. +refobjsec.fullname)
  3028. else if assigned(refobjsec) then
  3029. exemap.Add(' References '+refobjsec.fullname)
  3030. else if assigned(refgrp) then
  3031. exemap.Add(' References '+refgrp.Name)
  3032. else
  3033. internalerror(200603316);
  3034. end;
  3035. if assigned(refobjsec) then
  3036. AddToObjSectionWorkList(refobjsec);
  3037. end;
  3038. procedure DoVTableRef(vtable:TExeVTable;VTableIdx:longint);
  3039. var
  3040. i : longint;
  3041. objreloc : TObjRelocation;
  3042. begin
  3043. objreloc:=vtable.VTableRef(VTableIdx);
  3044. if assigned(objreloc) then
  3045. begin
  3046. { Process the relocation now if the ObjSection is
  3047. already processed and marked as used. Otherwise we leave it
  3048. unprocessed. It'll then be resolved when the ObjSection is
  3049. changed to Used }
  3050. if vtable.ExeSymbol.ObjSymbol.ObjSection.Used then
  3051. DoReloc(objreloc);
  3052. end;
  3053. { This recursive walking is done here instead of
  3054. in TExeVTable.VTableRef because we can now process
  3055. all needed relocations }
  3056. for i:=0 to vtable.ChildList.Count-1 do
  3057. DoVTableRef(TExeVTable(vtable.ChildList[i]),VTableIdx);
  3058. end;
  3059. procedure ProcessWorkList;
  3060. var
  3061. hs : string;
  3062. i,k : longint;
  3063. objsec : TObjSection;
  3064. objsym : TObjSymbol;
  3065. code : integer;
  3066. vtableidx : longint;
  3067. vtableexesym : TExeSymbol;
  3068. begin
  3069. while ObjSectionWorkList.Count>0 do
  3070. begin
  3071. objsec:=TObjSection(ObjSectionWorkList.Last);
  3072. if assigned(exemap) then
  3073. exemap.Add('Keeping '+objsec.FullName+' '+ToStr(objsec.ObjRelocations.Count)+' references');
  3074. ObjSectionWorkList.Delete(ObjSectionWorkList.Count-1);
  3075. { Process Relocations }
  3076. for i:=0 to objsec.ObjRelocations.count-1 do
  3077. DoReloc(TObjRelocation(objsec.ObjRelocations[i]));
  3078. { Process Virtual Entry calls }
  3079. if cs_link_opt_vtable in current_settings.globalswitches then
  3080. begin
  3081. for i:=0 to objsec.VTRefList.count-1 do
  3082. begin
  3083. objsym:=TObjSymbol(objsec.VTRefList[i]);
  3084. hs:=objsym.name;
  3085. Delete(hs,1,Pos('_',hs));
  3086. k:=Pos('$$',hs);
  3087. if k=0 then
  3088. internalerror(200603314);
  3089. vtableexesym:=texesymbol(FExeSymbolList.Find(Copy(hs,1,k-1)));
  3090. val(Copy(hs,k+2,length(hs)-k-1),vtableidx,code);
  3091. if (code<>0) then
  3092. internalerror(200603317);
  3093. if not assigned(vtableexesym) then
  3094. internalerror(200603315);
  3095. if not assigned(vtableexesym.vtable) then
  3096. internalerror(200603316);
  3097. DoVTableRef(vtableexesym.vtable,vtableidx);
  3098. end;
  3099. end;
  3100. end;
  3101. end;
  3102. var
  3103. i,j : longint;
  3104. exesec : TExeSection;
  3105. objdata : TObjData;
  3106. objsec : TObjSection;
  3107. begin
  3108. ObjSectionWorkList:=TFPObjectList.Create(false);
  3109. if assigned(exemap) then
  3110. exemap.AddHeader('Removing unreferenced sections');
  3111. { Initialize by marking all sections unused and
  3112. adding the sections with oso_keep flags to the ObjSectionWorkList }
  3113. for i:=0 to ObjDataList.Count-1 do
  3114. begin
  3115. ObjData:=TObjData(ObjDataList[i]);
  3116. for j:=0 to ObjData.ObjSectionList.Count-1 do
  3117. begin
  3118. objsec:=TObjSection(ObjData.ObjSectionList[j]);
  3119. objsec.Used:=false;
  3120. { TODO: remove debug section always keep}
  3121. if oso_debug in objsec.secoptions then
  3122. objsec.Used:=true;
  3123. if (oso_keep in objsec.secoptions) then
  3124. begin
  3125. AddToObjSectionWorkList(objsec);
  3126. if objsec.name='.fpc.n_links' then
  3127. objsec.Used:=false;
  3128. end;
  3129. end;
  3130. end;
  3131. if assigned(entrysym) then
  3132. AddToObjSectionWorkList(entrysym.exesymbol.objsymbol.objsection);
  3133. { Process all sections, add new sections to process based
  3134. on the symbol references }
  3135. ProcessWorkList;
  3136. { Handle stuff like .pdata, i.e. sections that are not referenced
  3137. but must be included if sections they reference are included.
  3138. Loop is necessary because .pdata can reference (via .xdata)
  3139. more text sections, VMTs of exception classes, etc. }
  3140. repeat
  3141. MarkTargetSpecificSections(ObjSectionWorkList);
  3142. if (ObjSectionWorkList.Count=0) then
  3143. break;
  3144. ProcessWorkList;
  3145. until False;
  3146. ObjSectionWorkList.Free;
  3147. ObjSectionWorkList:=nil;
  3148. { Remove unused objsections from ExeSectionList }
  3149. for i:=0 to ExeSectionList.Count-1 do
  3150. begin
  3151. exesec:=TExeSection(ExeSectionList[i]);
  3152. for j:=0 to exesec.ObjSectionlist.count-1 do
  3153. begin
  3154. objsec:=TObjSection(exesec.ObjSectionlist[j]);
  3155. if not objsec.used then
  3156. begin
  3157. if assigned(exemap) then
  3158. exemap.Add('Removing '+objsec.FullName);
  3159. exesec.ObjSectionlist[j]:=nil;
  3160. objsec.ReleaseData;
  3161. end;
  3162. end;
  3163. exesec.ObjSectionlist.Pack;
  3164. end;
  3165. end;
  3166. procedure TExeOutput.FixupRelocations;
  3167. var
  3168. i,j : longint;
  3169. exesec : TExeSection;
  3170. objsec : TObjSection;
  3171. begin
  3172. for i:=0 to ExeSectionList.Count-1 do
  3173. begin
  3174. exesec:=TExeSection(ExeSectionList[i]);
  3175. if not assigned(exesec) then
  3176. continue;
  3177. for j:=0 to exesec.ObjSectionlist.count-1 do
  3178. begin
  3179. objsec:=TObjSection(exesec.ObjSectionlist[j]);
  3180. if not objsec.Used then
  3181. internalerror(200603301);
  3182. if (objsec.ObjRelocations.Count>0) and
  3183. not assigned(objsec.data) then
  3184. internalerror(200205183);
  3185. DoRelocationFixup(objsec);
  3186. {for size = 0 data is not valid PM }
  3187. if assigned(objsec.data) and (objsec.data.size<>objsec.size) then
  3188. internalerror(2010092801);
  3189. end;
  3190. end;
  3191. end;
  3192. procedure TExeOutput.RemoveUnusedExeSymbols;
  3193. var
  3194. i : longint;
  3195. sym : TExeSymbol;
  3196. begin
  3197. { Removing unused symbols }
  3198. for i:=0 to ExeSymbolList.Count-1 do
  3199. begin
  3200. sym:=TExeSymbol(ExeSymbolList[i]);
  3201. { an unresolved weak symbol has objsection=nil }
  3202. if assigned(sym.ObjSymbol.objsection) and
  3203. (not sym.ObjSymbol.objsection.Used) then
  3204. ExeSymbolList[i]:=nil;
  3205. end;
  3206. ExeSymbolList.Pack;
  3207. end;
  3208. procedure TExeOutput.SetCurrMemPos(const AValue: qword);
  3209. begin
  3210. if AValue>MaxMemPos then
  3211. Message1(link_f_executable_too_big, target_os_string);
  3212. FCurrMemPos:=AValue;
  3213. end;
  3214. procedure TExeOutput.WriteExeSectionContent;
  3215. var
  3216. exesec : TExeSection;
  3217. objsec : TObjSection;
  3218. i,j : longint;
  3219. dpos,pad: aword;
  3220. begin
  3221. for j:=0 to ExeSectionList.Count-1 do
  3222. begin
  3223. exesec:=TExeSection(ExeSectionList[j]);
  3224. { don't write normal section if writing only debug info }
  3225. if (ExeWriteMode=ewm_dbgonly) and
  3226. (exesec.SecOptions*[oso_debug,oso_debug_copy]=[]) then
  3227. continue;
  3228. if oso_data in exesec.SecOptions then
  3229. begin
  3230. if exesec.DataPos<FWriter.Size then
  3231. InternalError(2012103001);
  3232. FWriter.Writezeros(exesec.DataPos-FWriter.Size);
  3233. for i:=0 to exesec.ObjSectionList.Count-1 do
  3234. begin
  3235. objsec:=TObjSection(exesec.ObjSectionList[i]);
  3236. if oso_data in objsec.secoptions then
  3237. begin
  3238. if not assigned(objsec.data) then
  3239. internalerror(200603042);
  3240. dpos:=objsec.MemPos-exesec.MemPos+exesec.DataPos;
  3241. pad:=dpos-FWriter.Size;
  3242. { objsection must be within SecAlign bytes from the previous one }
  3243. if (dpos<FWriter.Size) or
  3244. (pad>=max(objsec.SecAlign,1)) then
  3245. internalerror(200602251);
  3246. FWriter.writeZeros(pad);
  3247. FWriter.writearray(objsec.data);
  3248. end;
  3249. end;
  3250. end;
  3251. end;
  3252. end;
  3253. procedure TExeOutput.ReplaceExeSectionList(newlist: TFPList);
  3254. var
  3255. tmp: TFPHashObjectList;
  3256. i: longint;
  3257. begin
  3258. tmp:=TFPHashObjectList.Create(true);
  3259. for i:=0 to newlist.count-1 do
  3260. TFPHashObject(newlist[i]).ChangeOwner(tmp);
  3261. { prevent destruction of existing sections }
  3262. for i:=0 to ExeSectionList.count-1 do
  3263. ExeSectionList.List[i]:=nil;
  3264. FExeSectionList.Free;
  3265. FExeSectionList:=tmp;
  3266. end;
  3267. {****************************************************************************
  3268. TObjInput
  3269. ****************************************************************************}
  3270. constructor TObjInput.create;
  3271. begin
  3272. end;
  3273. procedure TObjInput.inputerror(const s : string);
  3274. begin
  3275. Comment(V_Error,s+' while reading '+InputFileName);
  3276. end;
  3277. class function TObjInput.CanReadObjData(AReader:TObjectReader):boolean;
  3278. begin
  3279. result:=false;
  3280. end;
  3281. procedure TObjInput.ReadSectionContent(Data:TObjData);
  3282. var
  3283. i: longint;
  3284. sec: TObjSection;
  3285. begin
  3286. for i:=0 to Data.ObjSectionList.Count-1 do
  3287. begin
  3288. sec:=TObjSection(Data.ObjSectionList[i]);
  3289. { Skip debug sections }
  3290. if (oso_debug in sec.SecOptions) and
  3291. (cs_link_strip in current_settings.globalswitches) and
  3292. not(cs_link_separate_dbg_file in current_settings.globalswitches) then
  3293. continue;
  3294. if assigned(sec.Data) then
  3295. begin
  3296. FReader.Seek(sec.datapos);
  3297. if not FReader.ReadArray(sec.data,sec.Size) then
  3298. begin
  3299. InputError('Can''t read object data');
  3300. exit;
  3301. end;
  3302. end;
  3303. end;
  3304. end;
  3305. {$ifdef MEMDEBUG}
  3306. initialization
  3307. memobjsymbols:=TMemDebug.create('ObjSymbols');
  3308. memobjsymbols.stop;
  3309. memobjsections:=TMemDebug.create('ObjSections');
  3310. memobjsections.stop;
  3311. finalization
  3312. memobjsymbols.free;
  3313. memobjsections.free;
  3314. {$endif MEMDEBUG}
  3315. end.