ogbase.pas 123 KB

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