ogbase.pas 137 KB

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