ogbase.pas 137 KB

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