ogbase.pas 97 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968
  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. type
  31. TObjSection = class;
  32. TObjData = class;
  33. TExeSection = class;
  34. TExeSymbol = class;
  35. TExeOutput = class;
  36. TObjRelocationType = (
  37. { Relocation to absolute address }
  38. RELOC_ABSOLUTE,
  39. {$ifdef x86_64}
  40. { 32bit Relocation to absolute address }
  41. RELOC_ABSOLUTE32,
  42. { 64 bit coff only }
  43. RELOC_RELATIVE_1,
  44. RELOC_RELATIVE_2,
  45. RELOC_RELATIVE_3,
  46. RELOC_RELATIVE_4,
  47. RELOC_RELATIVE_5,
  48. { PIC }
  49. RELOC_GOTPCREL,
  50. RELOC_PLT32,
  51. {$endif x86_64}
  52. {$ifdef i386}
  53. { PIC }
  54. RELOC_GOTPC,
  55. RELOC_GOT32,
  56. RELOC_PLT32,
  57. {$endif i386}
  58. {$ifdef arm}
  59. RELOC_RELATIVE_24,
  60. {$endif arm}
  61. { Relative relocation }
  62. RELOC_RELATIVE,
  63. { PECoff (Windows) RVA relocation }
  64. RELOC_RVA,
  65. { PECoff (Windows) section relocation, required by DWARF2 debug info }
  66. RELOC_SECREL32,
  67. { Generate a 0 value at the place of the relocation,
  68. this is used to remove unused vtable entries }
  69. RELOC_ZERO,
  70. { No relocation is needed. It is used in ARM object files.
  71. Also internal linker use this reloc to make virtual (not real)
  72. links to some sections }
  73. RELOC_NONE,
  74. { Darwin relocation, using PAIR }
  75. RELOC_PIC_PAIR
  76. );
  77. {$ifndef x86_64}
  78. const
  79. RELOC_ABSOLUTE32 = RELOC_ABSOLUTE;
  80. {$endif x86_64}
  81. const
  82. { stab types }
  83. N_GSYM = $20;
  84. N_STSYM = 38; { initialized const }
  85. N_LCSYM = 40; { non initialized variable}
  86. N_Function = $24; { function or const }
  87. N_TextLine = $44;
  88. N_DataLine = $46;
  89. N_BssLine = $48;
  90. N_RSYM = $40; { register variable }
  91. N_LSYM = $80;
  92. N_tsym = 160;
  93. N_SourceFile = $64;
  94. N_IncludeFile = $84;
  95. N_BINCL = $82;
  96. N_EINCL = $A2;
  97. N_LBRAC = $C0;
  98. N_EXCL = $C2;
  99. N_RBRAC = $E0;
  100. { GNU extensions }
  101. debuglinkname='.gnu_debuglink';
  102. type
  103. TObjSectionOption = (
  104. { Has Data available in the file }
  105. oso_Data,
  106. { Is loaded into memory }
  107. oso_load,
  108. { Not loaded into memory }
  109. oso_noload,
  110. { Read only }
  111. oso_readonly,
  112. { Read/Write }
  113. oso_write,
  114. { Contains executable instructions }
  115. oso_executable,
  116. { Never discard section }
  117. oso_keep,
  118. { Special common symbols }
  119. oso_common,
  120. { Contains debug info and can be stripped }
  121. oso_debug,
  122. { Contains only strings }
  123. oso_strings
  124. );
  125. TObjSectionOptions = set of TObjSectionOption;
  126. TObjSymbol = class(TFPHashObject)
  127. public
  128. bind : TAsmsymbind;
  129. typ : TAsmsymtype;
  130. { Current assemble pass, used to detect duplicate labels }
  131. pass : byte;
  132. objsection : TObjSection;
  133. symidx : longint;
  134. offset,
  135. size : aword;
  136. { Used for external and common solving during linking }
  137. exesymbol : TExeSymbol;
  138. { Darwin asm is using indirect symbols resolving }
  139. indsymbol : TObjSymbol;
  140. constructor create(AList:TFPHashObjectList;const AName:string);
  141. function address:aword;
  142. procedure SetAddress(apass:byte;aobjsec:TObjSection;abind:TAsmsymbind;atyp:Tasmsymtype);
  143. end;
  144. { Stabs is common for all targets }
  145. TObjStabEntry=packed record
  146. strpos : longint;
  147. ntype : byte;
  148. nother : byte;
  149. ndesc : word;
  150. nvalue : longint;
  151. end;
  152. PObjStabEntry=^TObjStabEntry;
  153. TObjRelocation = class
  154. DataOffset,
  155. orgsize : aword; { COFF: original size of the symbol to relocate }
  156. { ELF: explicit addend }
  157. symbol : TObjSymbol;
  158. objsection : TObjSection; { only used if symbol=nil }
  159. typ : TObjRelocationType;
  160. size : byte;
  161. constructor CreateSymbol(ADataOffset:aword;s:TObjSymbol;Atyp:TObjRelocationType);
  162. constructor CreateSymbolSize(ADataOffset:aword;s:TObjSymbol;Aorgsize:aword;Atyp:TObjRelocationType);
  163. constructor CreateSection(ADataOffset:aword;aobjsec:TObjSection;Atyp:TObjRelocationType);
  164. end;
  165. TObjSection = class(TFPHashObject)
  166. private
  167. FData : TDynamicArray;
  168. FSecOptions : TObjSectionOptions;
  169. FCachedFullName : pshortstring;
  170. procedure SetSecOptions(Aoptions:TObjSectionOptions);
  171. public
  172. ObjData : TObjData;
  173. SecSymIdx : longint; { index for the section in symtab }
  174. SecAlign : shortint; { alignment of the section }
  175. { section Data }
  176. Size,
  177. DataPos,
  178. MemPos : aword;
  179. DataAlignBytes : shortint;
  180. { Relocations (=references) to other sections }
  181. ObjRelocations : TFPObjectList;
  182. { Symbols this defines }
  183. ObjSymbolDefines : TFPObjectList;
  184. { executable linking }
  185. ExeSection : TExeSection;
  186. USed : Boolean;
  187. VTRefList : TFPObjectList;
  188. constructor create(AList:TFPHashObjectList;const Aname:string;Aalign:shortint;Aoptions:TObjSectionOptions);virtual;
  189. destructor destroy;override;
  190. function write(const d;l:aword):aword;
  191. function writestr(const s:string):aword;
  192. function WriteZeros(l:longword):aword;
  193. function setmempos(mpos:qword):qword;
  194. procedure setDatapos(var dpos:aword);
  195. procedure alloc(l:aword);
  196. procedure addsymReloc(ofs:aword;p:TObjSymbol;Reloctype:TObjRelocationType);
  197. procedure addsectionReloc(ofs:aword;aobjsec:TObjSection;Reloctype:TObjRelocationType);
  198. procedure AddSymbolDefine(p:TObjSymbol);
  199. procedure FixupRelocs(Exe: TExeOutput);virtual;
  200. procedure ReleaseData;
  201. function FullName:string;
  202. property Data:TDynamicArray read FData;
  203. property SecOptions:TObjSectionOptions read FSecOptions write SetSecOptions;
  204. end;
  205. TObjSectionClass = class of TObjSection;
  206. TString80 = string[80];
  207. TObjData = class(TLinkedListItem)
  208. private
  209. FName : TString80;
  210. FCurrObjSec : TObjSection;
  211. FObjSectionList : TFPHashObjectList;
  212. FCObjSection : TObjSectionClass;
  213. { Symbols that will be defined in this object file }
  214. FObjSymbolList : TFPHashObjectList;
  215. FCachedAsmSymbolList : TFPObjectList;
  216. { Special info sections that are written to during object generation }
  217. FStabsObjSec,
  218. FStabStrObjSec : TObjSection;
  219. procedure section_reset(p:TObject;arg:pointer);
  220. procedure section_afteralloc(p:TObject;arg:pointer);
  221. procedure section_afterwrite(p:TObject;arg:pointer);
  222. protected
  223. property CObjSection:TObjSectionClass read FCObjSection write FCObjSection;
  224. public
  225. CurrPass : byte;
  226. constructor create(const n:string);virtual;
  227. destructor destroy;override;
  228. { Sections }
  229. function sectionname(atype:TAsmSectiontype;const aname:string;aorder:TAsmSectionOrder):string;virtual;
  230. function sectiontype2options(atype:TAsmSectiontype):TObjSectionOptions;virtual;
  231. function sectiontype2align(atype:TAsmSectiontype):shortint;virtual;
  232. function createsection(atype:TAsmSectionType;const aname:string='';aorder:TAsmSectionOrder=secorder_default):TObjSection;
  233. function createsection(const aname:string;aalign:shortint;aoptions:TObjSectionOptions;DiscardDuplicate:boolean=true):TObjSection;virtual;
  234. procedure CreateDebugSections;virtual;
  235. function findsection(const aname:string):TObjSection;
  236. procedure setsection(asec:TObjSection);
  237. { Symbols }
  238. function createsymbol(const aname:string):TObjSymbol;
  239. function symboldefine(asmsym:TAsmSymbol):TObjSymbol;
  240. function symboldefine(const aname:string;abind:TAsmsymbind;atyp:Tasmsymtype):TObjSymbol;
  241. function symbolref(asmsym:TAsmSymbol):TObjSymbol;
  242. function symbolref(const aname:string):TObjSymbol;
  243. procedure ResetCachedAsmSymbols;
  244. { Allocation }
  245. procedure alloc(len:aword);
  246. procedure allocalign(len:shortint);
  247. procedure writebytes(const Data;len:aword);
  248. procedure writeReloc(Data:aint;len:aword;p:TObjSymbol;Reloctype:TObjRelocationType);virtual;abstract;
  249. procedure beforealloc;virtual;
  250. procedure beforewrite;virtual;
  251. procedure afteralloc;virtual;
  252. procedure afterwrite;virtual;
  253. procedure resetsections;
  254. procedure layoutsections(var datapos:aword);
  255. property Name:TString80 read FName;
  256. property CurrObjSec:TObjSection read FCurrObjSec;
  257. property ObjSymbolList:TFPHashObjectList read FObjSymbolList;
  258. property ObjSectionList:TFPHashObjectList read FObjSectionList;
  259. property StabsSec:TObjSection read FStabsObjSec write FStabsObjSec;
  260. property StabStrSec:TObjSection read FStabStrObjSec write FStabStrObjSec;
  261. end;
  262. TObjDataClass = class of TObjData;
  263. TObjOutput = class
  264. private
  265. FCObjData : TObjDataClass;
  266. protected
  267. { writer }
  268. FWriter : TObjectwriter;
  269. function writeData(Data:TObjData):boolean;virtual;abstract;
  270. property CObjData : TObjDataClass read FCObjData write FCObjData;
  271. procedure WriteSectionContent(Data:TObjData);
  272. public
  273. constructor create(AWriter:TObjectWriter);virtual;
  274. destructor destroy;override;
  275. function newObjData(const n:string):TObjData;
  276. function startObjectfile(const fn:string):boolean;
  277. function writeobjectfile(Data:TObjData):boolean;
  278. procedure exportsymbol(p:TObjSymbol);
  279. property Writer:TObjectWriter read FWriter;
  280. end;
  281. TObjOutputClass=class of TObjOutput;
  282. TObjInput = class
  283. private
  284. FCObjData : TObjDataClass;
  285. protected
  286. { reader }
  287. FReader : TObjectReader;
  288. InputFileName : string;
  289. property CObjData : TObjDataClass read FCObjData write FCObjData;
  290. procedure ReadSectionContent(Data:TObjData);
  291. public
  292. constructor create;virtual;
  293. destructor destroy;override;
  294. function newObjData(const n:string):TObjData;
  295. function ReadObjData(AReader:TObjectreader;Data:TObjData):boolean;virtual;abstract;
  296. procedure inputerror(const s : string);
  297. end;
  298. TObjInputClass=class of TObjInput;
  299. TVTableEntry=record
  300. ObjRelocation : TObjRelocation;
  301. orgreloctype : TObjRelocationType;
  302. Enabled,
  303. Used : Boolean;
  304. end;
  305. PVTableEntry=^TVTableEntry;
  306. TExeVTable = class
  307. private
  308. procedure CheckIdx(VTableIdx:longint);
  309. public
  310. ExeSymbol : TExeSymbol;
  311. EntryCnt : Longint;
  312. EntryArray : PVTableEntry;
  313. Consolidated : Boolean;
  314. ChildList : TFPObjectList;
  315. constructor Create(AExeSymbol:TExeSymbol);
  316. destructor Destroy;override;
  317. procedure AddChild(vt:TExeVTable);
  318. procedure AddEntry(VTableIdx:Longint);
  319. procedure SetVTableSize(ASize:longint);
  320. function VTableRef(VTableIdx:Longint):TObjRelocation;
  321. end;
  322. TSymbolState = (symstate_undefined,symstate_defined,symstate_common);
  323. TExeSymbol = class(TFPHashObject)
  324. ObjSymbol : TObjSymbol;
  325. State : TSymbolState;
  326. { Used for vmt references optimization }
  327. VTable : TExeVTable;
  328. end;
  329. TExeSection = class(TFPHashObject)
  330. private
  331. FSecSymIdx : longint;
  332. FObjSectionList : TFPObjectList;
  333. public
  334. Size,
  335. DataPos,
  336. MemPos : aword;
  337. SecAlign : shortint;
  338. SecOptions : TObjSectionOptions;
  339. constructor create(AList:TFPHashObjectList;const AName:string);virtual;
  340. destructor destroy;override;
  341. procedure AddObjSection(objsec:TObjSection);virtual;
  342. property ObjSectionList:TFPObjectList read FObjSectionList;
  343. property SecSymIdx:longint read FSecSymIdx write FSecSymIdx;
  344. end;
  345. TExeSectionClass=class of TExeSection;
  346. TStaticLibrary = class(TFPHashObject)
  347. private
  348. FArReader : TObjectReader;
  349. FObjInputClass : TObjInputClass;
  350. public
  351. constructor create(AList:TFPHashObjectList;const AName:string;AReader:TObjectReader;AObjInputClass:TObjInputClass);
  352. destructor destroy;override;
  353. property ArReader:TObjectReader read FArReader;
  354. property ObjInputClass:TObjInputClass read FObjInputClass;
  355. end;
  356. TImportLibrary = class(TFPHashObject)
  357. private
  358. FImportSymbolList : TFPHashObjectList;
  359. public
  360. constructor create(AList:TFPHashObjectList;const AName:string);
  361. destructor destroy;override;
  362. property ImportSymbolList:TFPHashObjectList read FImportSymbolList;
  363. end;
  364. TImportSymbol = class(TFPHashObject)
  365. private
  366. FOrdNr : longint;
  367. FIsVar : boolean;
  368. FMangledName : string;
  369. public
  370. constructor create(AList:TFPHashObjectList;const AName,AMangledName:string;AOrdNr:longint;AIsVar:boolean);
  371. property OrdNr: longint read FOrdNr;
  372. property MangledName: string read FMangledName;
  373. property IsVar: boolean read FIsVar;
  374. end;
  375. TExeWriteMode = (ewm_exefull,ewm_dbgonly,ewm_exeonly);
  376. TExeOutput = class
  377. private
  378. { ExeSectionList }
  379. FCObjData : TObjDataClass;
  380. FCExeSection : TExeSectionClass;
  381. FCurrExeSec : TExeSection;
  382. FExeSectionList : TFPHashObjectList;
  383. Fzeronr : longint;
  384. Fvaluesnr : longint;
  385. { Symbols }
  386. FExeSymbolList : TFPHashObjectList;
  387. FUnresolvedExeSymbols : TFPObjectList;
  388. FExternalObjSymbols,
  389. FCommonObjSymbols : TFPObjectList;
  390. FEntryName : string;
  391. FExeVTableList : TFPObjectList;
  392. { Objects }
  393. FObjDataList : TFPObjectList;
  394. { Position calculation }
  395. FImageBase : aword;
  396. FCurrMemPos : qword;
  397. procedure SetCurrMemPos(const AValue: qword);
  398. protected
  399. { writer }
  400. FExeWriteMode : TExeWriteMode;
  401. FWriter : TObjectwriter;
  402. commonObjSection : TObjSection;
  403. internalObjData : TObjData;
  404. EntrySym : TObjSymbol;
  405. SectionDataAlign,
  406. SectionMemAlign : aword;
  407. function writeData:boolean;virtual;abstract;
  408. property CExeSection:TExeSectionClass read FCExeSection write FCExeSection;
  409. property CObjData:TObjDataClass read FCObjData write FCObjData;
  410. procedure Order_ObjSectionList(ObjSectionList : TFPObjectList; const aPattern:string);virtual;
  411. procedure WriteExeSectionContent;
  412. public
  413. CurrDataPos : aword;
  414. MaxMemPos : qword;
  415. IsSharedLibrary : boolean;
  416. constructor create;virtual;
  417. destructor destroy;override;
  418. function FindExeSection(const aname:string):TExeSection;
  419. procedure AddObjData(ObjData:TObjData);
  420. procedure Load_Start;virtual;
  421. procedure Load_EntryName(const aname:string);virtual;
  422. procedure Load_Symbol(const aname:string);virtual;
  423. procedure Load_ProvideSymbol(const aname:string);virtual;
  424. procedure Load_IsSharedLibrary;
  425. procedure Load_ImageBase(const avalue:string);
  426. procedure Order_Start;virtual;
  427. procedure Order_End;virtual;
  428. procedure Order_ExeSection(const aname:string);virtual;
  429. procedure Order_Align(const avalue:string);virtual;
  430. procedure Order_Zeros(const avalue:string);virtual;
  431. procedure Order_Values(bytesize : aword; const avalue:string);virtual;
  432. procedure Order_Symbol(const aname:string);virtual;
  433. procedure Order_ProvideSymbol(const aname:string);virtual;
  434. procedure Order_EndExeSection;virtual;
  435. procedure Order_ObjSection(const aname:string);virtual;
  436. procedure MemPos_Start;virtual;
  437. procedure MemPos_Header;virtual;
  438. procedure MemPos_ExeSection(exesec:TExeSection);
  439. procedure MemPos_ExeSection(const aname:string);virtual;
  440. procedure MemPos_EndExeSection;virtual;
  441. procedure DataPos_Start;virtual;
  442. procedure DataPos_Header;virtual;
  443. procedure DataPos_ExeSection(exesec:TExeSection);
  444. procedure DataPos_ExeSection(const aname:string);virtual;
  445. procedure DataPos_EndExeSection;virtual;
  446. procedure DataPos_Symbols;virtual;
  447. procedure BuildVTableTree(VTInheritList,VTEntryList:TFPObjectList);
  448. procedure PackUnresolvedExeSymbols(const s:string);
  449. procedure ResolveSymbols(StaticLibraryList:TFPHashObjectList);
  450. procedure PrintMemoryMap;
  451. procedure FixupSymbols;
  452. procedure FixupRelocations;
  453. procedure MergeStabs;
  454. procedure RemoveUnreferencedSections;
  455. procedure RemoveEmptySections;
  456. procedure RemoveDebugInfo;
  457. procedure GenerateLibraryImports(ImportLibraryList:TFPHashObjectList);virtual;
  458. procedure GenerateDebugLink(const dbgname:string;dbgcrc:cardinal);
  459. function WriteExeFile(const fn:string):boolean;
  460. procedure ParseScript (linkscript:TCmdStrList); virtual;
  461. property Writer:TObjectWriter read FWriter;
  462. property ExeSectionList:TFPHashObjectList read FExeSectionList;
  463. property ObjDataList:TFPObjectList read FObjDataList;
  464. property ExeSymbolList:TFPHashObjectList read FExeSymbolList;
  465. property UnresolvedExeSymbols:TFPObjectList read FUnresolvedExeSymbols;
  466. property ExternalObjSymbols:TFPObjectList read FExternalObjSymbols;
  467. property CommonObjSymbols:TFPObjectList read FCommonObjSymbols;
  468. property ExeVTableList:TFPObjectList read FExeVTableList;
  469. property EntryName:string read FEntryName write FEntryName;
  470. property ImageBase:aword read FImageBase write FImageBase;
  471. property CurrExeSec:TExeSection read FCurrExeSec;
  472. property ExeWriteMode:TExeWriteMode read FExeWriteMode write FExeWriteMode;
  473. property CurrMemPos:qword read FCurrMemPos write SetCurrMemPos;
  474. end;
  475. TExeOutputClass=class of TExeOutput;
  476. var
  477. exeoutput : TExeOutput;
  478. implementation
  479. uses
  480. SysUtils,
  481. globals,verbose,fmodule,ogmap;
  482. const
  483. SectionDataMaxGrow = 4096;
  484. {$ifdef MEMDEBUG}
  485. var
  486. memobjsymbols,
  487. memobjsections : TMemDebug;
  488. {$endif MEMDEBUG}
  489. {*****************************************************************************
  490. TObjSymbol
  491. *****************************************************************************}
  492. constructor TObjSymbol.create(AList:TFPHashObjectList;const AName:string);
  493. begin;
  494. inherited create(AList,AName);
  495. bind:=AB_EXTERNAL;
  496. typ:=AT_NONE;
  497. symidx:=-1;
  498. size:=0;
  499. offset:=0;
  500. objsection:=nil;
  501. end;
  502. function TObjSymbol.address:aword;
  503. begin
  504. if assigned(objsection) then
  505. result:=offset+objsection.mempos
  506. else
  507. result:=0;
  508. end;
  509. procedure TObjSymbol.SetAddress(apass:byte;aobjsec:TObjSection;abind:TAsmsymbind;atyp:Tasmsymtype);
  510. begin
  511. if not(abind in [AB_GLOBAL,AB_LOCAL,AB_COMMON,AB_IMPORT]) then
  512. internalerror(200603016);
  513. if not assigned(aobjsec) then
  514. internalerror(200603017);
  515. if (bind in [AB_EXTERNAL,AB_LAZY]) or
  516. { Put all COMMON to GLOBAL in step 3 of
  517. TExeOutput.ResolveSymbols }
  518. ((abind=AB_GLOBAL) and (bind=AB_COMMON)) then
  519. begin
  520. { Do not change the AB_TYPE of common symbols yet }
  521. { This will be done in FixupSymbols }
  522. if (pass<>0) or (bind<>AB_COMMON) then
  523. bind:=abind;
  524. typ:=atyp;
  525. end
  526. else
  527. begin
  528. if pass=apass then
  529. begin
  530. Message1(asmw_e_duplicate_label,name);
  531. exit;
  532. end;
  533. end;
  534. pass:=apass;
  535. { Code can never grow after a pass }
  536. if assigned(objsection) and
  537. (objsection=aobjsec) and
  538. (aobjsec.size>offset) then
  539. internalerror(200603014);
  540. objsection:=aobjsec;
  541. offset:=aobjsec.size;
  542. end;
  543. {****************************************************************************
  544. TObjRelocation
  545. ****************************************************************************}
  546. constructor TObjRelocation.CreateSymbol(ADataOffset:aword;s:TObjSymbol;Atyp:TObjRelocationType);
  547. begin
  548. if not assigned(s) then
  549. internalerror(200603034);
  550. DataOffset:=ADataOffset;
  551. Symbol:=s;
  552. OrgSize:=0;
  553. ObjSection:=nil;
  554. Typ:=Atyp;
  555. end;
  556. constructor TObjRelocation.CreateSymbolSize(ADataOffset:aword;s:TObjSymbol;Aorgsize:aword;Atyp:TObjRelocationType);
  557. begin
  558. if not assigned(s) then
  559. internalerror(200603035);
  560. DataOffset:=ADataOffset;
  561. Symbol:=s;
  562. OrgSize:=Aorgsize;
  563. ObjSection:=nil;
  564. Typ:=Atyp;
  565. end;
  566. constructor TObjRelocation.CreateSection(ADataOffset:aword;aobjsec:TObjSection;Atyp:TObjRelocationType);
  567. begin
  568. if not assigned(aobjsec) then
  569. internalerror(200603036);
  570. DataOffset:=ADataOffset;
  571. Symbol:=nil;
  572. OrgSize:=0;
  573. ObjSection:=aobjsec;
  574. Typ:=Atyp;
  575. end;
  576. {****************************************************************************
  577. TObjSection
  578. ****************************************************************************}
  579. constructor TObjSection.create(AList:TFPHashObjectList;const Aname:string;Aalign:shortint;Aoptions:TObjSectionOptions);
  580. begin
  581. inherited Create(AList,Aname);
  582. { Data }
  583. Size:=0;
  584. Datapos:=0;
  585. mempos:=0;
  586. FData:=Nil;
  587. { Setting the secoptions allocates Data if needed }
  588. secoptions:=Aoptions;
  589. secalign:=Aalign;
  590. secsymidx:=0;
  591. { relocation }
  592. ObjRelocations:=TFPObjectList.Create(true);
  593. ObjSymbolDefines:=TFPObjectList.Create(false);
  594. VTRefList:=TFPObjectList.Create(false);
  595. end;
  596. destructor TObjSection.destroy;
  597. begin
  598. if assigned(Data) then
  599. Data.Free;
  600. stringdispose(FCachedFullName);
  601. ObjRelocations.Free;
  602. ObjSymbolDefines.Free;
  603. VTRefList.Free;
  604. inherited destroy;
  605. end;
  606. procedure TObjSection.SetSecOptions(Aoptions:TObjSectionOptions);
  607. begin
  608. FSecOptions:=FSecOptions+AOptions;
  609. if (oso_Data in secoptions) and
  610. not assigned(FData) then
  611. FData:=TDynamicArray.Create(SectionDataMaxGrow);
  612. end;
  613. function TObjSection.write(const d;l:aword):aword;
  614. begin
  615. result:=size;
  616. if assigned(Data) then
  617. begin
  618. if Size<>Data.size then
  619. internalerror(200602281);
  620. Data.write(d,l);
  621. inc(Size,l);
  622. end
  623. else
  624. internalerror(200602289);
  625. end;
  626. function TObjSection.writestr(const s:string):aword;
  627. begin
  628. result:=Write(s[1],length(s));
  629. end;
  630. function TObjSection.WriteZeros(l:longword):aword;
  631. var
  632. empty : array[0..1023] of byte;
  633. begin
  634. if l>sizeof(empty) then
  635. internalerror(200404082);
  636. if l>0 then
  637. begin
  638. fillchar(empty,l,0);
  639. result:=Write(empty,l);
  640. end
  641. else
  642. result:=Size;
  643. end;
  644. procedure TObjSection.setDatapos(var dpos:aword);
  645. begin
  646. if oso_Data in secoptions then
  647. begin
  648. { get aligned Datapos }
  649. Datapos:=align(dpos,secalign);
  650. Dataalignbytes:=Datapos-dpos;
  651. { return updated Datapos }
  652. dpos:=Datapos+size;
  653. end
  654. else
  655. Datapos:=dpos;
  656. end;
  657. function TObjSection.setmempos(mpos:qword):qword;
  658. begin
  659. mempos:=align(mpos,secalign);
  660. { return updated mempos }
  661. result:=mempos+size;
  662. end;
  663. procedure TObjSection.alloc(l:aword);
  664. begin
  665. inc(size,l);
  666. end;
  667. procedure TObjSection.addsymReloc(ofs:aword;p:TObjSymbol;Reloctype:TObjRelocationType);
  668. begin
  669. ObjRelocations.Add(TObjRelocation.CreateSymbol(ofs,p,reloctype));
  670. end;
  671. procedure TObjSection.addsectionReloc(ofs:aword;aobjsec:TObjSection;Reloctype:TObjRelocationType);
  672. begin
  673. ObjRelocations.Add(TObjRelocation.CreateSection(ofs,aobjsec,reloctype));
  674. end;
  675. procedure TObjSection.AddSymbolDefine(p:TObjSymbol);
  676. begin
  677. if p.bind<>AB_GLOBAL then
  678. exit;
  679. ObjSymbolDefines.Add(p);
  680. end;
  681. procedure TObjSection.FixupRelocs(Exe:TExeOutput);
  682. begin
  683. end;
  684. procedure TObjSection.ReleaseData;
  685. begin
  686. if assigned(FData) then
  687. begin
  688. FData.free;
  689. FData:=nil;
  690. end;
  691. ObjRelocations.free;
  692. ObjRelocations:=nil;
  693. ObjSymbolDefines.Free;
  694. ObjSymbolDefines:=nil;
  695. if assigned(FCachedFullName) then
  696. begin
  697. stringdispose(FCachedFullName);
  698. FCachedFullName:=nil;
  699. end;
  700. end;
  701. function TObjSection.FullName:string;
  702. begin
  703. if not assigned(FCachedFullName) then
  704. begin
  705. if assigned(ObjData) then
  706. FCachedFullName:=stringdup(ObjData.Name+'('+Name+')')
  707. else
  708. FCachedFullName:=stringdup(Name);
  709. end;
  710. result:=FCachedFullName^;
  711. end;
  712. {****************************************************************************
  713. TObjData
  714. ****************************************************************************}
  715. constructor TObjData.create(const n:string);
  716. begin
  717. inherited create;
  718. FName:=ExtractFileName(n);
  719. FObjSectionList:=TFPHashObjectList.Create(true);
  720. FStabsObjSec:=nil;
  721. FStabStrObjSec:=nil;
  722. { symbols }
  723. FObjSymbolList:=TFPHashObjectList.Create(true);
  724. FCachedAsmSymbolList:=TFPObjectList.Create(false);
  725. { section class type for creating of new sections }
  726. FCObjSection:=TObjSection;
  727. end;
  728. destructor TObjData.destroy;
  729. begin
  730. { Symbols }
  731. {$ifdef MEMDEBUG}
  732. MemObjSymbols.Start;
  733. {$endif}
  734. ResetCachedAsmSymbols;
  735. FCachedAsmSymbolList.free;
  736. FObjSymbolList.free;
  737. {$ifdef MEMDEBUG}
  738. MemObjSymbols.Stop;
  739. {$endif}
  740. { Sections }
  741. {$ifdef MEMDEBUG}
  742. MemObjSections.Start;
  743. {$endif}
  744. FObjSectionList.free;
  745. {$ifdef MEMDEBUG}
  746. MemObjSections.Stop;
  747. {$endif}
  748. inherited destroy;
  749. end;
  750. function TObjData.sectionname(atype:TAsmSectiontype;const aname:string;aorder:TAsmSectionOrder):string;
  751. const
  752. secnames : array[TAsmSectiontype] of string[length('__DATA, __datacoal_nt,coalesced')] = ('','',
  753. 'code',
  754. 'Data',
  755. 'Data',
  756. 'roData',
  757. 'bss',
  758. 'threadvar',
  759. 'pdata',
  760. 'stub',
  761. 'data_nonlazy',
  762. 'data_lazy',
  763. 'init_func',
  764. 'term_func',
  765. 'stab','stabstr',
  766. 'iData2','iData4','iData5','iData6','iData7','eData',
  767. 'eh_frame',
  768. 'debug_frame','debug_info','debug_line','debug_abbrev',
  769. 'fpc',
  770. 'toc',
  771. 'init',
  772. 'fini',
  773. 'objc_class',
  774. 'objc_meta_class',
  775. 'objc_cat_cls_meth',
  776. 'objc_cat_inst_meth',
  777. 'objc_protocol',
  778. 'objc_string_object',
  779. 'objc_cls_meth',
  780. 'objc_inst_meth',
  781. 'objc_cls_refs',
  782. 'objc_message_refs',
  783. 'objc_symbols',
  784. 'objc_category',
  785. 'objc_class_vars',
  786. 'objc_instance_vars',
  787. 'objc_module_info',
  788. 'objc_class_names',
  789. 'objc_meth_var_types',
  790. 'objc_meth_var_names',
  791. 'objc_selector_strs',
  792. 'objc_protocol_ext',
  793. 'objc_class_ext',
  794. 'objc_property',
  795. 'objc_image_info',
  796. 'objc_cstring_object',
  797. 'objc_sel_fixup',
  798. '__DATA,__objc_data',
  799. '__DATA,__objc_const',
  800. '.objc_superrefs',
  801. '__DATA, __datacoal_nt,coalesced',
  802. '.objc_classlist',
  803. '.objc_nlclasslist',
  804. '.objc_catlist',
  805. '.obcj_nlcatlist',
  806. '.objc_protolist'
  807. );
  808. var
  809. sep : string[3];
  810. begin
  811. if aname<>'' then
  812. begin
  813. case aorder of
  814. secorder_begin :
  815. sep:='.b_';
  816. secorder_end :
  817. sep:='.z_';
  818. else
  819. sep:='.n_';
  820. end;
  821. result:=secnames[atype]+sep+aname
  822. end
  823. else
  824. result:=secnames[atype];
  825. end;
  826. function TObjData.sectiontype2options(atype:TAsmSectiontype):TObjSectionOptions;
  827. const
  828. secoptions : array[TAsmSectiontype] of TObjSectionOptions = ([],
  829. {user} [oso_Data,oso_load,oso_write,oso_keep],
  830. {code} [oso_Data,oso_load,oso_readonly,oso_executable,oso_keep],
  831. {Data} [oso_Data,oso_load,oso_write,oso_keep],
  832. { TODO: Fix sec_rodata be read-only-with-relocs}
  833. {roData} [oso_Data,oso_load,oso_write,oso_keep],
  834. { TODO: Fix sec_rodata_norel be read-only/constant}
  835. {roData_norel} [oso_Data,oso_load,oso_write,oso_keep],
  836. {bss} [oso_load,oso_write,oso_keep],
  837. {threadvar} [oso_load,oso_write
  838. {$ifdef FPC_USE_TLS_DIRECTORY}
  839. ,oso_keep
  840. {$endif FPC_USE_TLS_DIRECTORY}
  841. ],
  842. {pdata} [oso_data,oso_load,oso_readonly {$ifndef x86_64},oso_keep{$endif}],
  843. {stub} [oso_Data,oso_load,oso_readonly,oso_executable],
  844. {data_nonlazy} [oso_Data,oso_load,oso_write],
  845. {data_lazy} [oso_Data,oso_load,oso_write],
  846. {init_func} [oso_Data,oso_load],
  847. {term_func} [oso_Data,oso_load],
  848. {stab} [oso_Data,oso_noload,oso_debug],
  849. {stabstr} [oso_Data,oso_noload,oso_strings,oso_debug],
  850. {iData2} [oso_Data,oso_load,oso_write],
  851. {iData4} [oso_Data,oso_load,oso_write],
  852. {iData5} [oso_Data,oso_load,oso_write],
  853. {iData6} [oso_Data,oso_load,oso_write],
  854. {iData7} [oso_Data,oso_load,oso_write],
  855. {eData} [oso_Data,oso_load,oso_readonly],
  856. {eh_frame} [oso_Data,oso_load,oso_readonly],
  857. {debug_frame} [oso_Data,oso_noload,oso_debug],
  858. {debug_info} [oso_Data,oso_noload,oso_debug],
  859. {debug_line} [oso_Data,oso_noload,oso_debug],
  860. {debug_abbrev} [oso_Data,oso_noload,oso_debug],
  861. {fpc} [oso_Data,oso_load,oso_write,oso_keep],
  862. {toc} [oso_Data,oso_load,oso_readonly],
  863. {init} [oso_Data,oso_load,oso_readonly,oso_executable,oso_keep],
  864. {fini} [oso_Data,oso_load,oso_readonly,oso_executable,oso_keep],
  865. {objc_class} [oso_data,oso_load],
  866. {objc_meta_class} [oso_data,oso_load],
  867. {objc_cat_cls_meth} [oso_data,oso_load],
  868. {objc_cat_inst_meth} [oso_data,oso_load],
  869. {objc_protocol} [oso_data,oso_load],
  870. {objc_string_object} [oso_data,oso_load],
  871. {objc_cls_meth} [oso_data,oso_load],
  872. {objc_inst_meth} [oso_data,oso_load],
  873. {objc_cls_refs} [oso_data,oso_load],
  874. {objc_message_refs} [oso_data,oso_load],
  875. {objc_symbols} [oso_data,oso_load],
  876. {objc_category} [oso_data,oso_load],
  877. {objc_class_vars} [oso_data,oso_load],
  878. {objc_instance_vars} [oso_data,oso_load],
  879. {objc_module_info} [oso_data,oso_load],
  880. {objc_class_names} [oso_data,oso_load],
  881. {objc_meth_var_types} [oso_data,oso_load],
  882. {objc_meth_var_names} [oso_data,oso_load],
  883. {objc_selector_strs} [oso_data,oso_load],
  884. {objc_protocol_ext} [oso_data,oso_load],
  885. {objc_class_ext} [oso_data,oso_load],
  886. {objc_property} [oso_data,oso_load],
  887. {objc_image_info} [oso_data,oso_load],
  888. {objc_cstring_object} [oso_data,oso_load],
  889. {objc_sel_fixup} [oso_data,oso_load],
  890. {sec_objc_data} [oso_data,oso_load],
  891. {sec_objc_const} [oso_data,oso_load],
  892. {sec_objc_sup_refs} [oso_data,oso_load],
  893. {sec_data_coalesced} [oso_data,oso_load],
  894. {sec_objc_classlist} [oso_data,oso_load],
  895. {sec_objc_nlclasslist} [oso_data,oso_load],
  896. {sec_objc_catlist} [oso_data,oso_load],
  897. {sec_objc_nlcatlist} [oso_data,oso_load],
  898. {sec_objc_protolist'} [oso_data,oso_load]
  899. );
  900. begin
  901. result:=secoptions[atype];
  902. end;
  903. function TObjData.sectiontype2align(atype:TAsmSectiontype):shortint;
  904. begin
  905. case atype of
  906. sec_stabstr,sec_debug_info,sec_debug_line,sec_debug_abbrev:
  907. result:=1;
  908. sec_code,
  909. sec_bss,
  910. sec_data:
  911. result:=16;
  912. { For idata (at least idata2) it must be 4 bytes, because
  913. an entry is always (also in win64) 20 bytes and aligning
  914. on 8 bytes will insert 4 bytes between the entries resulting
  915. in a corrupt idata section.
  916. Same story with .pdata, it has 4-byte elements which should
  917. be packed without gaps. }
  918. sec_idata2,sec_idata4,sec_idata5,sec_idata6,sec_idata7,sec_pdata:
  919. result:=4;
  920. else
  921. result:=sizeof(pint);
  922. end;
  923. end;
  924. function TObjData.createsection(atype:TAsmSectionType;const aname:string;aorder:TAsmSectionOrder):TObjSection;
  925. begin
  926. result:=createsection(sectionname(atype,aname,aorder),sectiontype2align(atype),sectiontype2options(atype));
  927. end;
  928. function TObjData.createsection(const aname:string;aalign:shortint;aoptions:TObjSectionOptions;DiscardDuplicate:boolean):TObjSection;
  929. begin
  930. if DiscardDuplicate then
  931. result:=TObjSection(FObjSectionList.Find(aname))
  932. else
  933. result:=nil;
  934. if not assigned(result) then
  935. begin
  936. result:=CObjSection.create(FObjSectionList,aname,aalign,aoptions);
  937. result.ObjData:=self;
  938. end;
  939. FCurrObjSec:=result;
  940. end;
  941. procedure TObjData.CreateDebugSections;
  942. begin
  943. end;
  944. function TObjData.FindSection(const aname:string):TObjSection;
  945. begin
  946. result:=TObjSection(FObjSectionList.Find(aname));
  947. end;
  948. procedure TObjData.setsection(asec:TObjSection);
  949. begin
  950. if asec.ObjData<>self then
  951. internalerror(200403041);
  952. FCurrObjSec:=asec;
  953. end;
  954. function TObjData.createsymbol(const aname:string):TObjSymbol;
  955. begin
  956. result:=TObjSymbol(FObjSymbolList.Find(aname));
  957. if not assigned(result) then
  958. result:=TObjSymbol.Create(FObjSymbolList,aname);
  959. end;
  960. function TObjData.symboldefine(asmsym:TAsmSymbol):TObjSymbol;
  961. begin
  962. if assigned(asmsym) then
  963. begin
  964. if not assigned(asmsym.cachedObjSymbol) then
  965. begin
  966. result:=symboldefine(asmsym.name,asmsym.bind,asmsym.typ);
  967. asmsym.cachedObjSymbol:=result;
  968. FCachedAsmSymbolList.add(asmsym);
  969. end
  970. else
  971. begin
  972. result:=TObjSymbol(asmsym.cachedObjSymbol);
  973. result.SetAddress(CurrPass,CurrObjSec,asmsym.bind,asmsym.typ);
  974. { Register also in TObjSection }
  975. CurrObjSec.AddSymbolDefine(result);
  976. end;
  977. end
  978. else
  979. result:=nil;
  980. end;
  981. function TObjData.symboldefine(const aname:string;abind:TAsmsymbind;atyp:Tasmsymtype):TObjSymbol;
  982. begin
  983. if not assigned(CurrObjSec) then
  984. internalerror(200603051);
  985. result:=CreateSymbol(aname);
  986. { Register also in TObjSection }
  987. CurrObjSec.AddSymbolDefine(result);
  988. result.SetAddress(CurrPass,CurrObjSec,abind,atyp);
  989. end;
  990. function TObjData.symbolref(asmsym:TAsmSymbol):TObjSymbol;
  991. begin
  992. if assigned(asmsym) then
  993. begin
  994. if not assigned(asmsym.cachedObjSymbol) then
  995. begin
  996. result:=symbolref(asmsym.name);
  997. asmsym.cachedObjSymbol:=result;
  998. FCachedAsmSymbolList.add(asmsym);
  999. end
  1000. else
  1001. result:=TObjSymbol(asmsym.cachedObjSymbol);
  1002. end
  1003. else
  1004. result:=nil;
  1005. end;
  1006. function TObjData.symbolref(const aname:string):TObjSymbol;
  1007. begin
  1008. if not assigned(CurrObjSec) then
  1009. internalerror(200603052);
  1010. result:=CreateSymbol(aname);
  1011. end;
  1012. procedure TObjData.ResetCachedAsmSymbols;
  1013. var
  1014. i : longint;
  1015. begin
  1016. for i:=0 to FCachedAsmSymbolList.Count-1 do
  1017. tasmsymbol(FCachedAsmSymbolList[i]).cachedObjSymbol:=nil;
  1018. FCachedAsmSymbolList.Clear;
  1019. end;
  1020. procedure TObjData.writebytes(const Data;len:aword);
  1021. begin
  1022. if not assigned(CurrObjSec) then
  1023. internalerror(200402251);
  1024. CurrObjSec.write(Data,len);
  1025. end;
  1026. procedure TObjData.alloc(len:aword);
  1027. begin
  1028. if not assigned(CurrObjSec) then
  1029. internalerror(200402252);
  1030. CurrObjSec.alloc(len);
  1031. end;
  1032. procedure TObjData.allocalign(len:shortint);
  1033. begin
  1034. if not assigned(CurrObjSec) then
  1035. internalerror(200402253);
  1036. CurrObjSec.alloc(align(CurrObjSec.size,len)-CurrObjSec.size);
  1037. end;
  1038. procedure TObjData.section_afteralloc(p:TObject;arg:pointer);
  1039. begin
  1040. with TObjSection(p) do
  1041. alloc(align(size,secalign)-size);
  1042. end;
  1043. procedure TObjData.section_afterwrite(p:TObject;arg:pointer);
  1044. begin
  1045. with TObjSection(p) do
  1046. begin
  1047. if assigned(Data) then
  1048. writezeros(align(size,secalign)-size);
  1049. end;
  1050. end;
  1051. procedure TObjData.section_reset(p:TObject;arg:pointer);
  1052. begin
  1053. with TObjSection(p) do
  1054. begin
  1055. Size:=0;
  1056. Datapos:=0;
  1057. mempos:=0;
  1058. end;
  1059. end;
  1060. procedure TObjData.beforealloc;
  1061. begin
  1062. { create stabs sections if debugging }
  1063. if assigned(StabsSec) then
  1064. begin
  1065. StabsSec.Alloc(sizeof(TObjStabEntry));
  1066. StabStrSec.Alloc(1);
  1067. end;
  1068. end;
  1069. procedure TObjData.beforewrite;
  1070. var
  1071. s : string[1];
  1072. hstab : TObjStabEntry;
  1073. begin
  1074. { create stabs sections if debugging }
  1075. if assigned(StabsSec) then
  1076. begin
  1077. { Create dummy HdrSym stab, it will be overwritten in AfterWrite }
  1078. fillchar(hstab,sizeof(hstab),0);
  1079. StabsSec.Write(hstab,sizeof(hstab));
  1080. { start of stabstr }
  1081. s:=#0;
  1082. StabStrSec.write(s[1],length(s));
  1083. end;
  1084. end;
  1085. procedure TObjData.afteralloc;
  1086. begin
  1087. FObjSectionList.ForEachCall(@section_afteralloc,nil);
  1088. end;
  1089. procedure TObjData.afterwrite;
  1090. var
  1091. s : string[1];
  1092. hstab : TObjStabEntry;
  1093. begin
  1094. FObjSectionList.ForEachCall(@section_afterwrite,nil);
  1095. { For the stab section we need an HdrSym which can now be
  1096. calculated more easily }
  1097. if assigned(StabsSec) then
  1098. begin
  1099. { end of stabstr }
  1100. s:=#0;
  1101. StabStrSec.write(s[1],length(s));
  1102. { header stab }
  1103. hstab.strpos:=1;
  1104. hstab.ntype:=0;
  1105. hstab.nother:=0;
  1106. hstab.ndesc:=(StabsSec.Size div sizeof(TObjStabEntry))-1;
  1107. hstab.nvalue:=StabStrSec.Size;
  1108. StabsSec.Data.seek(0);
  1109. StabsSec.Data.write(hstab,sizeof(hstab));
  1110. end;
  1111. end;
  1112. procedure TObjData.resetsections;
  1113. begin
  1114. FObjSectionList.ForEachCall(@section_reset,nil);
  1115. end;
  1116. procedure TObjData.layoutsections(var DataPos:aword);
  1117. var
  1118. i: longint;
  1119. begin
  1120. for i:=0 to FObjSectionList.Count-1 do
  1121. TObjSection(FObjSectionList[i]).setDatapos(DataPos);
  1122. end;
  1123. {****************************************************************************
  1124. TObjOutput
  1125. ****************************************************************************}
  1126. constructor TObjOutput.create(AWriter:TObjectWriter);
  1127. begin
  1128. FWriter:=AWriter;
  1129. CObjData:=TObjData;
  1130. end;
  1131. destructor TObjOutput.destroy;
  1132. begin
  1133. inherited destroy;
  1134. end;
  1135. function TObjOutput.newObjData(const n:string):TObjData;
  1136. begin
  1137. result:=CObjData.create(n);
  1138. if (cs_use_lineinfo in current_settings.globalswitches) or
  1139. (cs_debuginfo in current_settings.moduleswitches) then
  1140. result.CreateDebugSections;
  1141. end;
  1142. function TObjOutput.startObjectfile(const fn:string):boolean;
  1143. begin
  1144. result:=false;
  1145. { start the writer already, so the .a generation can initialize
  1146. the position of the current objectfile }
  1147. if not FWriter.createfile(fn) then
  1148. Comment(V_Fatal,'Can''t create object '+fn);
  1149. result:=true;
  1150. end;
  1151. function TObjOutput.writeobjectfile(Data:TObjData):boolean;
  1152. begin
  1153. if errorcount=0 then
  1154. result:=writeData(Data)
  1155. else
  1156. result:=true;
  1157. { close the writer }
  1158. FWriter.closefile;
  1159. end;
  1160. procedure TObjOutput.exportsymbol(p:TObjSymbol);
  1161. begin
  1162. { export globals and common symbols, this is needed
  1163. for .a files }
  1164. if p.bind in [AB_GLOBAL,AB_COMMON] then
  1165. FWriter.writesym(p.name);
  1166. end;
  1167. procedure TObjOutput.WriteSectionContent(Data:TObjData);
  1168. var
  1169. i:longint;
  1170. sec:TObjSection;
  1171. begin
  1172. for i:=0 to Data.ObjSectionList.Count-1 do
  1173. begin
  1174. sec:=TObjSection(Data.ObjSectionList[i]);
  1175. if (oso_data in sec.SecOptions) then
  1176. begin
  1177. if sec.Data=nil then
  1178. internalerror(200403073);
  1179. FWriter.writezeros(sec.dataalignbytes);
  1180. if sec.Datapos<>FWriter.ObjSize then
  1181. internalerror(200604031);
  1182. FWriter.writearray(sec.data);
  1183. end;
  1184. end;
  1185. end;
  1186. {****************************************************************************
  1187. TExeVTable
  1188. ****************************************************************************}
  1189. constructor TExeVTable.Create(AExeSymbol:TExeSymbol);
  1190. begin
  1191. ExeSymbol:=AExeSymbol;
  1192. if ExeSymbol.State=symstate_undefined then
  1193. internalerror(200604012);
  1194. ChildList:=TFPObjectList.Create(false);
  1195. end;
  1196. destructor TExeVTable.Destroy;
  1197. begin
  1198. ChildList.Free;
  1199. if assigned(EntryArray) then
  1200. Freemem(EntryArray);
  1201. end;
  1202. procedure TExeVTable.CheckIdx(VTableIdx:longint);
  1203. var
  1204. OldEntryCnt : longint;
  1205. begin
  1206. if VTableIdx>=EntryCnt then
  1207. begin
  1208. OldEntryCnt:=EntryCnt;
  1209. EntryCnt:=VTableIdx+1;
  1210. ReAllocMem(EntryArray,EntryCnt*sizeof(TVTableEntry));
  1211. FillChar(EntryArray[OldEntryCnt],(EntryCnt-OldEntryCnt)*sizeof(TVTableEntry),0);
  1212. end;
  1213. end;
  1214. procedure TExeVTable.AddChild(vt:TExeVTable);
  1215. begin
  1216. ChildList.Add(vt);
  1217. end;
  1218. procedure TExeVTable.AddEntry(VTableIdx:Longint);
  1219. var
  1220. i : longint;
  1221. objreloc : TObjRelocation;
  1222. vtblentryoffset : aword;
  1223. begin
  1224. CheckIdx(VTableIdx);
  1225. vtblentryoffset:=ExeSymbol.ObjSymbol.Offset+longword(VTableIdx)*sizeof(pint);
  1226. { Find and disable relocation }
  1227. for i:=0 to ExeSymbol.ObjSymbol.ObjSection.ObjRelocations.Count-1 do
  1228. begin
  1229. objreloc:=TObjRelocation(ExeSymbol.ObjSymbol.ObjSection.ObjRelocations[i]);
  1230. if objreloc.dataoffset=vtblentryoffset then
  1231. begin
  1232. EntryArray[VTableIdx].ObjRelocation:=objreloc;
  1233. EntryArray[VTableIdx].OrgRelocType:=objreloc.typ;
  1234. objreloc.typ:=RELOC_ZERO;
  1235. break;
  1236. end;
  1237. end;
  1238. if not assigned(EntryArray[VTableIdx].ObjRelocation) then
  1239. internalerror(200604011);
  1240. end;
  1241. procedure TExeVTable.SetVTableSize(ASize:longint);
  1242. begin
  1243. if EntryCnt<>0 then
  1244. internalerror(200603313);
  1245. EntryCnt:=ASize div sizeof(pint);
  1246. EntryArray:=AllocMem(EntryCnt*sizeof(TVTableEntry));
  1247. end;
  1248. function TExeVTable.VTableRef(VTableIdx:Longint):TObjRelocation;
  1249. begin
  1250. result:=nil;
  1251. CheckIdx(VTableIdx);
  1252. if EntryArray[VTableIdx].Used then
  1253. exit;
  1254. { Restore relocation if available }
  1255. if assigned(EntryArray[VTableIdx].ObjRelocation) then
  1256. begin
  1257. EntryArray[VTableIdx].ObjRelocation.typ:=EntryArray[VTableIdx].OrgRelocType;
  1258. result:=EntryArray[VTableIdx].ObjRelocation;
  1259. end;
  1260. EntryArray[VTableIdx].Used:=true;
  1261. end;
  1262. {****************************************************************************
  1263. TExeSection
  1264. ****************************************************************************}
  1265. constructor TExeSection.create(AList:TFPHashObjectList;const AName:string);
  1266. begin
  1267. inherited create(AList,AName);
  1268. Size:=0;
  1269. MemPos:=0;
  1270. DataPos:=0;
  1271. FSecSymIdx:=0;
  1272. FObjSectionList:=TFPObjectList.Create(false);
  1273. end;
  1274. destructor TExeSection.destroy;
  1275. begin
  1276. ObjSectionList.Free;
  1277. inherited destroy;
  1278. end;
  1279. procedure TExeSection.AddObjSection(objsec:TObjSection);
  1280. begin
  1281. ObjSectionList.Add(objsec);
  1282. if (SecOptions<>[]) then
  1283. begin
  1284. { Only if the section contains (un)initialized data the
  1285. data flag must match. This check is not needed if the
  1286. section is empty for a symbol allocation }
  1287. if (objsec.size>0) and
  1288. ((oso_Data in SecOptions)<>(oso_Data in objsec.SecOptions)) then
  1289. Comment(V_Error,'Incompatible section options');
  1290. end
  1291. else
  1292. begin
  1293. { inherit section options }
  1294. SecAlign:=objsec.SecAlign;
  1295. SecOptions:=SecOptions+objsec.SecOptions;
  1296. end;
  1297. { relate ObjSection to ExeSection, and mark it Used by default }
  1298. objsec.ExeSection:=self;
  1299. objsec.Used:=true;
  1300. end;
  1301. {****************************************************************************
  1302. TStaticLibrary
  1303. ****************************************************************************}
  1304. constructor TStaticLibrary.create(AList:TFPHashObjectList;const AName:string;AReader:TObjectReader;AObjInputClass:TObjInputClass);
  1305. begin
  1306. inherited create(AList,AName);
  1307. FArReader:=AReader;
  1308. FObjInputClass:=AObjInputClass;
  1309. end;
  1310. destructor TStaticLibrary.destroy;
  1311. begin
  1312. ArReader.Free;
  1313. inherited destroy;
  1314. end;
  1315. {****************************************************************************
  1316. TImportLibrary
  1317. ****************************************************************************}
  1318. constructor TImportLibrary.create(AList:TFPHashObjectList;const AName:string);
  1319. begin
  1320. inherited create(AList,AName);
  1321. FImportSymbolList:=TFPHashObjectList.Create(true);
  1322. end;
  1323. destructor TImportLibrary.destroy;
  1324. begin
  1325. ImportSymbolList.Free;
  1326. inherited destroy;
  1327. end;
  1328. {****************************************************************************
  1329. TImportSymbol
  1330. ****************************************************************************}
  1331. constructor TImportSymbol.create(AList:TFPHashObjectList;
  1332. const AName,AMangledName:string;AOrdNr:longint;AIsVar:boolean);
  1333. begin
  1334. inherited Create(AList, AName);
  1335. FOrdNr:=AOrdNr;
  1336. FIsVar:=AIsVar;
  1337. FMangledName:=AMangledName;
  1338. { Replace ? and @ in import name, since GNU AS does not allow these characters in symbol names. }
  1339. { This allows to import VC++ mangled names from DLLs. }
  1340. if target_info.system in systems_all_windows then
  1341. begin
  1342. Replace(FMangledName,'?','__q$$');
  1343. {$ifdef arm}
  1344. { @ symbol is not allowed in ARM assembler only }
  1345. Replace(FMangledName,'@','__a$$');
  1346. {$endif arm}
  1347. end;
  1348. end;
  1349. {****************************************************************************
  1350. TExeOutput
  1351. ****************************************************************************}
  1352. constructor TExeOutput.create;
  1353. begin
  1354. { init writer }
  1355. FWriter:=TObjectwriter.create;
  1356. FExeWriteMode:=ewm_exefull;
  1357. { object files }
  1358. FObjDataList:=TFPObjectList.Create(true);
  1359. { symbols }
  1360. FExeSymbolList:=TFPHashObjectList.Create(true);
  1361. FUnresolvedExeSymbols:=TFPObjectList.Create(false);
  1362. FExternalObjSymbols:=TFPObjectList.Create(false);
  1363. FCommonObjSymbols:=TFPObjectList.Create(false);
  1364. FExeVTableList:=TFPObjectList.Create(false);
  1365. FEntryName:='start';
  1366. { sections }
  1367. FExeSectionList:=TFPHashObjectList.Create(true);
  1368. FImageBase:=0;
  1369. {$ifdef cpu16bitaddr}
  1370. SectionMemAlign:=$10;
  1371. SectionDataAlign:=$10;
  1372. {$else cpu16bitaddr}
  1373. SectionMemAlign:=$1000;
  1374. SectionDataAlign:=$200;
  1375. {$endif cpu16bitaddr}
  1376. FCExeSection:=TExeSection;
  1377. FCObjData:=TObjData;
  1378. end;
  1379. destructor TExeOutput.destroy;
  1380. begin
  1381. FExeSymbolList.free;
  1382. UnresolvedExeSymbols.free;
  1383. ExternalObjSymbols.free;
  1384. CommonObjSymbols.free;
  1385. ExeVTableList.free;
  1386. FExeSectionList.free;
  1387. ObjDatalist.free;
  1388. FWriter.free;
  1389. inherited destroy;
  1390. end;
  1391. function TExeOutput.WriteExeFile(const fn:string):boolean;
  1392. begin
  1393. result:=false;
  1394. if FWriter.createfile(fn) then
  1395. begin
  1396. { Only write the .o if there are no errors }
  1397. if errorcount=0 then
  1398. result:=writedata
  1399. else
  1400. result:=true;
  1401. { close the writer }
  1402. FWriter.closefile;
  1403. end
  1404. else
  1405. Comment(V_Fatal,'Can''t create executable '+fn);
  1406. end;
  1407. procedure TExeOutput.ParseScript (linkscript:TCmdStrList);
  1408. begin
  1409. end;
  1410. function TExeOutput.FindExeSection(const aname:string):TExeSection;
  1411. begin
  1412. result:=TExeSection(ExeSectionList.Find(aname));
  1413. end;
  1414. procedure TExeOutput.AddObjData(ObjData:TObjData);
  1415. begin
  1416. if ObjData.classtype<>FCObjData then
  1417. Comment(V_Error,'Invalid input object format for '+ObjData.name+' got '+ObjData.classname+' expected '+FCObjData.classname);
  1418. ObjDataList.Add(ObjData);
  1419. end;
  1420. procedure TExeOutput.Load_Start;
  1421. begin
  1422. ObjDataList.Clear;
  1423. { Globals defined in the linker script }
  1424. if not assigned(internalObjData) then
  1425. internalObjData:=CObjData.create('*Internal*');
  1426. AddObjData(internalObjData);
  1427. { Common Data section }
  1428. commonObjSection:=internalObjData.createsection(sec_bss,'');
  1429. { setting SecOptions acts as 'include' }
  1430. commonObjSection.SecOptions:=[oso_common];
  1431. end;
  1432. procedure TExeOutput.Load_EntryName(const aname:string);
  1433. begin
  1434. FEntryName:=aname;
  1435. end;
  1436. procedure TExeOutput.Load_IsSharedLibrary;
  1437. begin
  1438. IsSharedLibrary:=true;
  1439. end;
  1440. procedure TExeOutput.Load_ImageBase(const avalue:string);
  1441. var
  1442. code : integer;
  1443. objsec : TObjSection;
  1444. objsym : TObjSymbol;
  1445. exesym : TExeSymbol;
  1446. begin
  1447. val(avalue,FImageBase,code);
  1448. if code<>0 then
  1449. Comment(V_Error,'Invalid number '+avalue);
  1450. { Create __image_base__ symbol, create the symbol
  1451. in a section with adress 0 and at offset 0 }
  1452. objsec:=internalObjData.createsection('*__image_base__',0,[]);
  1453. internalObjData.setsection(objsec);
  1454. objsym:=internalObjData.SymbolDefine('__image_base__',AB_GLOBAL,AT_FUNCTION);
  1455. exesym:=texesymbol.Create(FExeSymbolList,objsym.name);
  1456. exesym.ObjSymbol:=objsym;
  1457. end;
  1458. procedure TExeOutput.Load_Symbol(const aname:string);
  1459. begin
  1460. internalObjData.createsection('*'+aname,0,[]);
  1461. internalObjData.SymbolDefine(aname,AB_GLOBAL,AT_FUNCTION);
  1462. end;
  1463. procedure TExeOutput.Load_ProvideSymbol(const aname:string);
  1464. begin
  1465. if assigned(ExeSymbolList.Find(aname)) then
  1466. exit;
  1467. internalObjData.createsection('*'+aname,0,[]);
  1468. // Use AB_COMMON to avoid muliple defined complaints
  1469. internalObjData.SymbolDefine(aname,AB_COMMON,AT_DATA);
  1470. end;
  1471. procedure TExeOutput.Order_Start;
  1472. begin
  1473. end;
  1474. procedure TExeOutput.Order_End;
  1475. begin
  1476. internalObjData.afterwrite;
  1477. end;
  1478. procedure TExeOutput.Order_ExeSection(const aname:string);
  1479. var
  1480. sec : TExeSection;
  1481. begin
  1482. sec:=FindExeSection(aname);
  1483. if not assigned(sec) then
  1484. sec:=CExeSection.create(ExeSectionList,aname);
  1485. { Clear ExeSection contents }
  1486. FCurrExeSec:=sec;
  1487. end;
  1488. procedure TExeOutput.Order_EndExeSection;
  1489. begin
  1490. if not assigned(CurrExeSec) then
  1491. internalerror(200602184);
  1492. FCurrExeSec:=nil;
  1493. end;
  1494. procedure TExeOutput.Order_ObjSection(const aname:string);
  1495. var
  1496. i,j : longint;
  1497. ObjData : TObjData;
  1498. objsec : TObjSection;
  1499. TmpObjSectionList : TFPObjectList;
  1500. begin
  1501. if not assigned(CurrExeSec) then
  1502. internalerror(200602181);
  1503. TmpObjSectionList:=TFPObjectList.Create(false);
  1504. for i:=0 to ObjDataList.Count-1 do
  1505. begin
  1506. ObjData:=TObjData(ObjDataList[i]);
  1507. for j:=0 to ObjData.ObjSectionList.Count-1 do
  1508. begin
  1509. objsec:=TObjSection(ObjData.ObjSectionList[j]);
  1510. if (not objsec.Used) and
  1511. MatchPattern(aname,objsec.name) then
  1512. TmpObjSectionList.Add(objsec);
  1513. end;
  1514. end;
  1515. { Order list if needed }
  1516. Order_ObjSectionList(TmpObjSectionList,aname);
  1517. { Add the (ordered) list to the current ExeSection }
  1518. for i:=0 to TmpObjSectionList.Count-1 do
  1519. begin
  1520. objsec:=TObjSection(TmpObjSectionList[i]);
  1521. CurrExeSec.AddObjSection(objsec);
  1522. end;
  1523. TmpObjSectionList.Free;
  1524. end;
  1525. procedure TExeOutput.Order_ObjSectionList(ObjSectionList : TFPObjectList; const aPattern:string);
  1526. begin
  1527. end;
  1528. procedure TExeOutput.Order_Symbol(const aname:string);
  1529. var
  1530. ObjSection : TObjSection;
  1531. begin
  1532. ObjSection:=internalObjData.findsection('*'+aname);
  1533. if not assigned(ObjSection) then
  1534. internalerror(200603041);
  1535. CurrExeSec.AddObjSection(ObjSection);
  1536. end;
  1537. procedure TExeOutput.Order_ProvideSymbol(const aname:string);
  1538. var
  1539. ObjSection : TObjSection;
  1540. begin
  1541. ObjSection:=internalObjData.findsection('*'+aname);
  1542. if not assigned(ObjSection) then
  1543. internalerror(200603041);
  1544. { Only include this section if the symbol doesn't
  1545. exist otherwisee }
  1546. if not assigned(ExeSymbolList.Find(aname)) then
  1547. CurrExeSec.AddObjSection(ObjSection);
  1548. end;
  1549. procedure TExeOutput.Order_Align(const avalue:string);
  1550. var
  1551. code : integer;
  1552. alignval : shortint;
  1553. objsec : TObjSection;
  1554. begin
  1555. val(avalue,alignval,code);
  1556. if code<>0 then
  1557. Comment(V_Error,'Invalid number '+avalue);
  1558. if alignval<=0 then
  1559. exit;
  1560. { Create an empty section with the required aligning }
  1561. inc(Fzeronr);
  1562. objsec:=internalObjData.createsection('*align'+tostr(Fzeronr),alignval,CurrExeSec.SecOptions+[oso_Data,oso_keep]);
  1563. CurrExeSec.AddObjSection(objsec);
  1564. end;
  1565. procedure TExeOutput.Order_Zeros(const avalue:string);
  1566. var
  1567. zeros : array[0..1023] of byte;
  1568. code : integer;
  1569. len : longint;
  1570. objsec : TObjSection;
  1571. begin
  1572. val(avalue,len,code);
  1573. if code<>0 then
  1574. Comment(V_Error,'Invalid number '+avalue);
  1575. if len<=0 then
  1576. exit;
  1577. if len>sizeof(zeros) then
  1578. internalerror(200602254);
  1579. fillchar(zeros,len,0);
  1580. inc(Fzeronr);
  1581. objsec:=internalObjData.createsection('*zeros'+tostr(Fzeronr),0,CurrExeSec.SecOptions+[oso_Data,oso_keep]);
  1582. internalObjData.writebytes(zeros,len);
  1583. CurrExeSec.AddObjSection(objsec);
  1584. end;
  1585. procedure TExeOutput.Order_Values(bytesize : aword; const avalue:string);
  1586. const
  1587. MAXVAL = 128;
  1588. var
  1589. bytevalues : array[0..MAXVAL-1] of byte;
  1590. twobytevalues : array[0..MAXVAL-1] of word;
  1591. fourbytevalues : array[0..MAXVAL-1] of dword;
  1592. eightbytevalues : array[0..MAXVAL-1] of qword;
  1593. allvals, oneval : string;
  1594. len, commapos : longint;
  1595. indexpos, code : integer;
  1596. anumval : qword;
  1597. signedval : int64;
  1598. objsec : TObjSection;
  1599. begin
  1600. indexpos:=0;
  1601. allvals:=avalue;
  1602. repeat
  1603. commapos:=pos(',',allvals);
  1604. if commapos>0 then
  1605. begin
  1606. oneval:=trim(copy(allvals,1,commapos-1));
  1607. allvals:=copy(allvals,commapos+1,length(allvals));
  1608. end
  1609. else
  1610. begin
  1611. oneval:=trim(allvals);
  1612. allvals:='';
  1613. end;
  1614. if oneval<>'' then
  1615. begin
  1616. if oneval[1]='-' then
  1617. begin
  1618. val(oneval,signedval,code);
  1619. anumval:=qword(signedval);
  1620. end
  1621. else
  1622. val(oneval,anumval,code);
  1623. if code<>0 then
  1624. Comment(V_Error,'Invalid number '+avalue)
  1625. else
  1626. begin
  1627. if (indexpos<MAXVAL) then
  1628. begin
  1629. if source_info.endian<>target_info.endian then
  1630. swapendian(anumval);
  1631. { No range checking here }
  1632. if bytesize=1 then
  1633. bytevalues[indexpos]:=byte(anumval)
  1634. else if bytesize=2 then
  1635. twobytevalues[indexpos]:=word(anumval)
  1636. else if bytesize=4 then
  1637. fourbytevalues[indexpos]:=dword(anumval)
  1638. else if bytesize=8 then
  1639. eightbytevalues[indexpos]:=anumval;
  1640. inc(indexpos);
  1641. end
  1642. else
  1643. Comment(V_Error,'Buffer overrun in Order_values');
  1644. end;
  1645. end;
  1646. until allvals='';
  1647. if indexpos=0 then
  1648. begin
  1649. Comment(V_Error,'Invalid number '+avalue);
  1650. exit;
  1651. end;
  1652. if indexpos=MAXVAL then
  1653. begin
  1654. Comment(V_Error,'Too many values '+avalue);
  1655. internalerror(200602254);
  1656. end;
  1657. len:=bytesize*indexpos;
  1658. inc(Fvaluesnr);
  1659. objsec:=internalObjData.createsection('*values'+tostr(Fvaluesnr),0,CurrExeSec.SecOptions+[oso_Data,oso_keep]);
  1660. if bytesize=1 then
  1661. internalObjData.writebytes(bytevalues,len)
  1662. else if bytesize=2 then
  1663. internalObjData.writebytes(twobytevalues,len)
  1664. else if bytesize=4 then
  1665. internalObjData.writebytes(fourbytevalues,len)
  1666. else if bytesize=8 then
  1667. internalObjData.writebytes(eightbytevalues,len);
  1668. CurrExeSec.AddObjSection(objsec);
  1669. end;
  1670. procedure TExeOutput.MemPos_Start;
  1671. begin
  1672. CurrMemPos:=0;
  1673. end;
  1674. procedure TExeOutput.MemPos_Header;
  1675. begin
  1676. end;
  1677. procedure TExeOutput.MemPos_ExeSection(exesec:TExeSection);
  1678. var
  1679. i : longint;
  1680. objsec : TObjSection;
  1681. begin
  1682. { Alignment of ExeSection }
  1683. CurrMemPos:=align(CurrMemPos,SectionMemAlign);
  1684. exesec.MemPos:=CurrMemPos;
  1685. { set position of object ObjSections }
  1686. for i:=0 to exesec.ObjSectionList.Count-1 do
  1687. begin
  1688. objsec:=TObjSection(exesec.ObjSectionList[i]);
  1689. CurrMemPos:=objsec.setmempos(CurrMemPos);
  1690. end;
  1691. { calculate size of the section }
  1692. exesec.Size:=CurrMemPos-exesec.MemPos;
  1693. end;
  1694. procedure TExeOutput.MemPos_ExeSection(const aname:string);
  1695. begin
  1696. { Section can be removed }
  1697. FCurrExeSec:=FindExeSection(aname);
  1698. if not assigned(CurrExeSec) then
  1699. exit;
  1700. MemPos_ExeSection(CurrExeSec);
  1701. end;
  1702. procedure TExeOutput.MemPos_EndExeSection;
  1703. begin
  1704. if not assigned(CurrExeSec) then
  1705. exit;
  1706. FCurrExeSec:=nil;
  1707. end;
  1708. procedure TExeOutput.DataPos_Start;
  1709. begin
  1710. end;
  1711. procedure TExeOutput.DataPos_Header;
  1712. begin
  1713. end;
  1714. procedure TExeOutput.DataPos_ExeSection(exesec:TExeSection);
  1715. var
  1716. i : longint;
  1717. objsec : TObjSection;
  1718. begin
  1719. { don't write normal section if writing only debug info }
  1720. if (ExeWriteMode=ewm_dbgonly) and
  1721. not(oso_debug in exesec.SecOptions) then
  1722. exit;
  1723. if (oso_Data in exesec.SecOptions) then
  1724. begin
  1725. CurrDataPos:=align(CurrDataPos,SectionDataAlign);
  1726. exesec.DataPos:=CurrDataPos;
  1727. end;
  1728. { set position of object ObjSections }
  1729. for i:=0 to exesec.ObjSectionList.Count-1 do
  1730. begin
  1731. objsec:=TObjSection(exesec.ObjSectionList[i]);
  1732. if (oso_Data in objsec.SecOptions) then
  1733. begin
  1734. if not(oso_Data in exesec.SecOptions) then
  1735. internalerror(200603043);
  1736. if not assigned(objsec.Data) then
  1737. internalerror(200603044);
  1738. objsec.setDatapos(CurrDataPos);
  1739. end;
  1740. end;
  1741. end;
  1742. procedure TExeOutput.DataPos_ExeSection(const aname:string);
  1743. begin
  1744. { Section can be removed }
  1745. FCurrExeSec:=FindExeSection(aname);
  1746. if not assigned(CurrExeSec) then
  1747. exit;
  1748. DataPos_ExeSection(CurrExeSec);
  1749. end;
  1750. procedure TExeOutput.DataPos_EndExeSection;
  1751. begin
  1752. if not assigned(CurrExeSec) then
  1753. exit;
  1754. FCurrExeSec:=nil;
  1755. end;
  1756. procedure TExeOutput.DataPos_Symbols;
  1757. var
  1758. i : longint;
  1759. sym : TExeSymbol;
  1760. begin
  1761. { Removing unused symbols }
  1762. for i:=0 to ExeSymbolList.Count-1 do
  1763. begin
  1764. sym:=TExeSymbol(ExeSymbolList[i]);
  1765. if not sym.ObjSymbol.objsection.Used then
  1766. ExeSymbolList[i]:=nil;
  1767. end;
  1768. ExeSymbolList.Pack;
  1769. end;
  1770. procedure TExeOutput.BuildVTableTree(VTInheritList,VTEntryList:TFPObjectList);
  1771. var
  1772. hs : string;
  1773. code : integer;
  1774. i,k,
  1775. vtableidx : longint;
  1776. vtableexesym,
  1777. childexesym,
  1778. parentexesym : TExeSymbol;
  1779. objsym : TObjSymbol;
  1780. begin
  1781. { Build inheritance tree from VTINHERIT }
  1782. for i:=0 to VTInheritList.Count-1 do
  1783. begin
  1784. objsym:=TObjSymbol(VTInheritList[i]);
  1785. hs:=objsym.name;
  1786. { VTINHERIT_<ChildVMTName>$$<ParentVMTName> }
  1787. Delete(hs,1,Pos('_',hs));
  1788. k:=Pos('$$',hs);
  1789. if k=0 then
  1790. internalerror(200603311);
  1791. childexesym:=texesymbol(FExeSymbolList.Find(Copy(hs,1,k-1)));
  1792. parentexesym:=texesymbol(FExeSymbolList.Find(Copy(hs,k+2,length(hs)-k-1)));
  1793. if not assigned(childexesym) or
  1794. not assigned(parentexesym)then
  1795. internalerror(200603312);
  1796. if not assigned(childexesym.vtable) then
  1797. begin
  1798. childexesym.vtable:=TExeVTable.Create(childexesym);
  1799. ExeVTableList.Add(childexesym.vtable);
  1800. end;
  1801. if not assigned(parentexesym.vtable) then
  1802. begin
  1803. parentexesym.vtable:=TExeVTable.Create(parentexesym);
  1804. ExeVTableList.Add(parentexesym.vtable);
  1805. end;
  1806. childexesym.vtable.SetVTableSize(childexesym.ObjSymbol.Size);
  1807. if parentexesym<>childexesym then
  1808. parentexesym.vtable.AddChild(childexesym.vtable);
  1809. end;
  1810. { Find VTable entries from VTENTRY }
  1811. for i:=0 to VTEntryList.Count-1 do
  1812. begin
  1813. objsym:=TObjSymbol(VTEntryList[i]);
  1814. hs:=objsym.name;
  1815. { VTENTRY_<VTableName>$$<Index> }
  1816. Delete(hs,1,Pos('_',hs));
  1817. k:=Pos('$$',hs);
  1818. if k=0 then
  1819. internalerror(200603319);
  1820. vtableexesym:=texesymbol(FExeSymbolList.Find(Copy(hs,1,k-1)));
  1821. val(Copy(hs,k+2,length(hs)-k-1),vtableidx,code);
  1822. if (code<>0) then
  1823. internalerror(200603318);
  1824. if not assigned(vtableexesym) then
  1825. internalerror(2006033110);
  1826. vtableexesym.vtable.AddEntry(vtableidx);
  1827. end;
  1828. end;
  1829. procedure TExeOutput.PackUnresolvedExeSymbols(const s:string);
  1830. var
  1831. i : longint;
  1832. exesym : TExeSymbol;
  1833. begin
  1834. { Generate a list of Unresolved External symbols }
  1835. for i:=0 to UnresolvedExeSymbols.count-1 do
  1836. begin
  1837. exesym:=TExeSymbol(UnresolvedExeSymbols[i]);
  1838. if exesym.State<>symstate_undefined then
  1839. UnresolvedExeSymbols[i]:=nil;
  1840. end;
  1841. UnresolvedExeSymbols.Pack;
  1842. Comment(V_Debug,'Number of unresolved externals '+s+' '+tostr(UnresolvedExeSymbols.Count));
  1843. end;
  1844. procedure TExeOutput.ResolveSymbols(StaticLibraryList:TFPHashObjectList);
  1845. var
  1846. ObjData : TObjData;
  1847. exesym : TExeSymbol;
  1848. objsym,
  1849. commonsym : TObjSymbol;
  1850. objinput : TObjInput;
  1851. StaticLibrary : TStaticLibrary;
  1852. firstarchive,
  1853. firstcommon : boolean;
  1854. i,j : longint;
  1855. VTEntryList,
  1856. VTInheritList : TFPObjectList;
  1857. procedure LoadObjDataSymbols(ObjData:TObjData);
  1858. var
  1859. j : longint;
  1860. hs : string;
  1861. exesym : TExeSymbol;
  1862. objsym : TObjSymbol;
  1863. begin
  1864. for j:=0 to ObjData.ObjSymbolList.Count-1 do
  1865. begin
  1866. objsym:=TObjSymbol(ObjData.ObjSymbolList[j]);
  1867. { From the local symbols we are only interressed in the
  1868. VTENTRY and VTINHERIT symbols }
  1869. if objsym.bind=AB_LOCAL then
  1870. begin
  1871. if cs_link_opt_vtable in current_settings.globalswitches then
  1872. begin
  1873. hs:=objsym.name;
  1874. if (hs[1]='V') then
  1875. begin
  1876. if Copy(hs,1,5)='VTREF' then
  1877. begin
  1878. if not assigned(objsym.ObjSection.VTRefList) then
  1879. objsym.ObjSection.VTRefList:=TFPObjectList.Create(false);
  1880. objsym.ObjSection.VTRefList.Add(objsym);
  1881. end
  1882. else if Copy(hs,1,7)='VTENTRY' then
  1883. VTEntryList.Add(objsym)
  1884. else if Copy(hs,1,9)='VTINHERIT' then
  1885. VTInheritList.Add(objsym);
  1886. end;
  1887. end;
  1888. continue;
  1889. end;
  1890. { Search for existing exesymbol }
  1891. exesym:=texesymbol(FExeSymbolList.Find(objsym.name));
  1892. if not assigned(exesym) then
  1893. begin
  1894. exesym:=texesymbol.Create(FExeSymbolList,objsym.name);
  1895. exesym.ObjSymbol:=objsym;
  1896. end;
  1897. objsym.ExeSymbol:=exesym;
  1898. case objsym.bind of
  1899. AB_GLOBAL :
  1900. begin
  1901. if exesym.State<>symstate_defined then
  1902. begin
  1903. exesym.ObjSymbol:=objsym;
  1904. exesym.State:=symstate_defined;
  1905. end
  1906. else
  1907. Comment(V_Error,'Multiple defined symbol '+objsym.name);
  1908. end;
  1909. AB_EXTERNAL :
  1910. begin
  1911. ExternalObjSymbols.add(objsym);
  1912. { Register unresolved symbols only the first time they
  1913. are registered }
  1914. if exesym.ObjSymbol=objsym then
  1915. UnresolvedExeSymbols.Add(exesym);
  1916. end;
  1917. AB_COMMON :
  1918. begin
  1919. if exesym.State=symstate_undefined then
  1920. begin
  1921. exesym.ObjSymbol:=objsym;
  1922. exesym.State:=symstate_common;
  1923. end;
  1924. CommonObjSymbols.add(objsym);
  1925. end;
  1926. end;
  1927. end;
  1928. end;
  1929. begin
  1930. VTEntryList:=TFPObjectList.Create(false);
  1931. VTInheritList:=TFPObjectList.Create(false);
  1932. {
  1933. The symbol resolving is done in 3 steps:
  1934. 1. Register symbols from objects
  1935. 2. Find symbols in static libraries
  1936. 3. Define stil undefined common symbols
  1937. }
  1938. { Step 1, Register symbols from objects }
  1939. for i:=0 to ObjDataList.Count-1 do
  1940. begin
  1941. ObjData:=TObjData(ObjDataList[i]);
  1942. LoadObjDataSymbols(ObjData);
  1943. end;
  1944. PackUnresolvedExeSymbols('in objects');
  1945. { Step 2, Find unresolved symbols in the libraries }
  1946. firstarchive:=true;
  1947. for i:=0 to StaticLibraryList.Count-1 do
  1948. begin
  1949. StaticLibrary:=TStaticLibrary(StaticLibraryList[i]);
  1950. { Process list of Unresolved External symbols, we need
  1951. to use a while loop because the list can be extended when
  1952. we load members from the library. }
  1953. j:=0;
  1954. while (j<UnresolvedExeSymbols.count) do
  1955. begin
  1956. exesym:=TExeSymbol(UnresolvedExeSymbols[j]);
  1957. { Check first if the symbol is still undefined }
  1958. if exesym.State=symstate_undefined then
  1959. begin
  1960. if StaticLibrary.ArReader.OpenFile(exesym.name) then
  1961. begin
  1962. if assigned(exemap) then
  1963. begin
  1964. if firstarchive then
  1965. begin
  1966. exemap.Add('');
  1967. exemap.Add('Archive member included because of file (symbol)');
  1968. exemap.Add('');
  1969. firstarchive:=false;
  1970. end;
  1971. exemap.Add(StaticLibrary.ArReader.FileName+' - '+
  1972. {exesym.ObjSymbol.ObjSection.FullName+}
  1973. '('+exesym.Name+')');
  1974. end;
  1975. objinput:=StaticLibrary.ObjInputClass.Create;
  1976. objdata:=objinput.newObjData(StaticLibrary.ArReader.FileName);
  1977. objinput.ReadObjData(StaticLibrary.ArReader,objdata);
  1978. objinput.free;
  1979. AddObjData(objdata);
  1980. LoadObjDataSymbols(objdata);
  1981. StaticLibrary.ArReader.CloseFile;
  1982. end;
  1983. end;
  1984. inc(j);
  1985. end;
  1986. end;
  1987. PackUnresolvedExeSymbols('after static libraries');
  1988. { Step 3, Match common symbols or add to the globals }
  1989. firstcommon:=true;
  1990. for i:=0 to CommonObjSymbols.count-1 do
  1991. begin
  1992. objsym:=TObjSymbol(CommonObjSymbols[i]);
  1993. if objsym.exesymbol.State=symstate_defined then
  1994. begin
  1995. if objsym.exesymbol.ObjSymbol.size<>objsym.size then
  1996. Comment(V_Debug,'Size of common symbol '+objsym.name+' is different, expected '+tostr(objsym.size)+' got '+tostr(objsym.exesymbol.ObjSymbol.size));
  1997. end
  1998. else
  1999. begin
  2000. { allocate new objsymbol in .bss of *COMMON* and assign
  2001. it to the exesymbol }
  2002. if firstcommon then
  2003. begin
  2004. if assigned(exemap) then
  2005. exemap.AddCommonSymbolsHeader;
  2006. firstcommon:=false;
  2007. end;
  2008. internalObjData.setsection(commonObjSection);
  2009. internalObjData.allocalign(var_align(objsym.size));
  2010. commonsym:=internalObjData.symboldefine(objsym.name,AB_GLOBAL,AT_FUNCTION);
  2011. commonsym.size:=objsym.size;
  2012. internalObjData.alloc(objsym.size);
  2013. if assigned(exemap) then
  2014. exemap.AddCommonSymbol(commonsym);
  2015. { Assign to the exesymbol }
  2016. objsym.exesymbol.objsymbol:=commonsym;
  2017. objsym.exesymbol.state:=symstate_defined;
  2018. end;
  2019. end;
  2020. PackUnresolvedExeSymbols('after defining COMMON symbols');
  2021. { Find entry symbol and print in map }
  2022. exesym:=texesymbol(ExeSymbolList.Find(EntryName));
  2023. if assigned(exesym) then
  2024. begin
  2025. EntrySym:=exesym.ObjSymbol;
  2026. if assigned(exemap) then
  2027. begin
  2028. exemap.Add('');
  2029. exemap.Add('Entry symbol '+EntryName);
  2030. end;
  2031. end
  2032. else
  2033. Comment(V_Error,'Entrypoint '+EntryName+' not defined');
  2034. { Generate VTable tree }
  2035. if cs_link_opt_vtable in current_settings.globalswitches then
  2036. BuildVTableTree(VTInheritList,VTEntryList);
  2037. VTInheritList.Free;
  2038. VTEntryList.Free;
  2039. end;
  2040. procedure TExeOutput.GenerateDebugLink(const dbgname:string;dbgcrc:cardinal);
  2041. var
  2042. debuglink : array[0..1023] of byte;
  2043. len : longint;
  2044. objsec : TObjSection;
  2045. exesec : TExeSection;
  2046. begin
  2047. { From the gdb manual chapter 15. GDB Files:
  2048. * A filename, with any leading directory components removed, followed by a zero byte,
  2049. * zero to three bytes of padding, as needed to reach the next four-byte boundary within the section, and
  2050. * a four-byte CRC checksum, stored in the same endianness used for the executable file itself. The checksum is computed
  2051. on the debugging information file's full contents by the function given below, passing zero as the crc argument.
  2052. }
  2053. fillchar(debuglink,sizeof(debuglink),0);
  2054. len:=0;
  2055. move(dbgname[1],debuglink[len],length(dbgname));
  2056. inc(len,length(dbgname)+1);
  2057. len:=align(len,4);
  2058. if source_info.endian<>target_info.endian then
  2059. SwapEndian(dbgcrc);
  2060. move(dbgcrc,debuglink[len],sizeof(cardinal));
  2061. inc(len,4);
  2062. { Add section }
  2063. exesec:=FindExeSection(debuglinkname);
  2064. if not assigned(exesec) then
  2065. exesec:=CExeSection.create(ExeSectionList,debuglinkname);
  2066. exesec.SecOptions:=[oso_data,oso_keep];
  2067. exesec.SecAlign:=4;
  2068. objsec:=internalObjData.createsection(exesec.name,0,exesec.SecOptions);
  2069. internalObjData.writebytes(debuglink,len);
  2070. exesec.AddObjSection(objsec);
  2071. end;
  2072. procedure TExeOutput.GenerateLibraryImports(ImportLibraryList:TFPHashObjectList);
  2073. begin
  2074. end;
  2075. procedure TExeOutput.PrintMemoryMap;
  2076. var
  2077. exesec : TExeSection;
  2078. objsec : TObjSection;
  2079. objsym : TObjSymbol;
  2080. i,j,k : longint;
  2081. begin
  2082. if not assigned(exemap) then
  2083. exit;
  2084. exemap.AddMemoryMapHeader(ImageBase);
  2085. for i:=0 to ExeSectionList.Count-1 do
  2086. begin
  2087. exesec:=TExeSection(ExeSectionList[i]);
  2088. exemap.AddMemoryMapExeSection(exesec);
  2089. for j:=0 to exesec.ObjSectionList.count-1 do
  2090. begin
  2091. objsec:=TObjSection(exesec.ObjSectionList[j]);
  2092. exemap.AddMemoryMapObjectSection(objsec);
  2093. for k:=0 to objsec.ObjSymbolDefines.Count-1 do
  2094. begin
  2095. objsym:=TObjSymbol(objsec.ObjSymbolDefines[k]);
  2096. exemap.AddMemoryMapSymbol(objsym);
  2097. end;
  2098. end;
  2099. end;
  2100. end;
  2101. procedure TExeOutput.FixupSymbols;
  2102. procedure UpdateSymbol(objsym:TObjSymbol);
  2103. begin
  2104. objsym.bind:=objsym.ExeSymbol.ObjSymbol.bind;
  2105. objsym.offset:=objsym.ExeSymbol.ObjSymbol.offset;
  2106. objsym.size:=objsym.ExeSymbol.ObjSymbol.size;
  2107. objsym.typ:=objsym.ExeSymbol.ObjSymbol.typ;
  2108. objsym.ObjSection:=objsym.ExeSymbol.ObjSymbol.ObjSection;
  2109. end;
  2110. var
  2111. i : longint;
  2112. objsym : TObjSymbol;
  2113. exesym : TExeSymbol;
  2114. begin
  2115. { Print list of Unresolved External symbols }
  2116. for i:=0 to UnresolvedExeSymbols.count-1 do
  2117. begin
  2118. exesym:=TExeSymbol(UnresolvedExeSymbols[i]);
  2119. if exesym.State<>symstate_defined then
  2120. Comment(V_Error,'Undefined symbol: '+exesym.name);
  2121. end;
  2122. {
  2123. Fixing up symbols is done in the following steps:
  2124. 1. Update common references
  2125. 2. Update external references
  2126. }
  2127. { Step 1, Update commons }
  2128. for i:=0 to CommonObjSymbols.count-1 do
  2129. begin
  2130. objsym:=TObjSymbol(CommonObjSymbols[i]);
  2131. if objsym.bind<>AB_COMMON then
  2132. internalerror(200606241);
  2133. UpdateSymbol(objsym);
  2134. end;
  2135. { Step 2, Update externals }
  2136. for i:=0 to ExternalObjSymbols.count-1 do
  2137. begin
  2138. objsym:=TObjSymbol(ExternalObjSymbols[i]);
  2139. if objsym.bind<>AB_EXTERNAL then
  2140. internalerror(200606242);
  2141. UpdateSymbol(objsym);
  2142. end;
  2143. end;
  2144. procedure TExeOutput.MergeStabs;
  2145. var
  2146. stabexesec,
  2147. stabstrexesec : TExeSection;
  2148. relocsec,
  2149. currstabsec,
  2150. currstabstrsec,
  2151. mergedstabsec,
  2152. mergedstabstrsec : TObjSection;
  2153. hstabreloc,
  2154. currstabreloc : TObjRelocation;
  2155. i,j : longint;
  2156. currstabrelocidx,
  2157. mergestabcnt,
  2158. stabcnt : longword;
  2159. skipstab : boolean;
  2160. skipfun : boolean;
  2161. hstab : TObjStabEntry;
  2162. stabrelocofs : longword;
  2163. buf : array[0..1023] of byte;
  2164. bufend,
  2165. bufsize : longint;
  2166. begin
  2167. stabexesec:=FindExeSection('.stab');
  2168. stabstrexesec:=FindExeSection('.stabstr');
  2169. if (stabexesec=nil) or
  2170. (stabstrexesec=nil) or
  2171. (stabexesec.ObjSectionlist.count=0) then
  2172. exit;
  2173. { Create new stabsection }
  2174. stabRelocofs:=pbyte(@hstab.nvalue)-pbyte(@hstab);
  2175. mergedstabsec:=internalObjData.CreateSection(sec_stab,'');
  2176. mergedstabstrsec:=internalObjData.CreateSection(sec_stabstr,'');
  2177. { write stab for hdrsym }
  2178. fillchar(hstab,sizeof(TObjStabEntry),0);
  2179. mergedstabsec.write(hstab,sizeof(TObjStabEntry));
  2180. mergestabcnt:=1;
  2181. { .stabstr starts with a #0 }
  2182. buf[0]:=0;
  2183. mergedstabstrsec.write(buf[0],1);
  2184. skipfun:=false;
  2185. { Copy stabs and corresponding Relocations }
  2186. for i:=0 to stabexesec.ObjSectionList.Count-1 do
  2187. begin
  2188. currstabsec:=TObjSection(stabexesec.ObjSectionList[i]);
  2189. currstabstrsec:=currstabsec.ObjData.findsection('.stabstr');
  2190. if assigned(currstabstrsec) then
  2191. begin
  2192. stabcnt:=currstabsec.Data.size div sizeof(TObjStabEntry);
  2193. currstabsec.Data.seek(0);
  2194. currstabrelocidx:=0;
  2195. for j:=0 to stabcnt-1 do
  2196. begin
  2197. hstabreloc:=nil;
  2198. skipstab:=false;
  2199. currstabsec.Data.read(hstab,sizeof(TObjStabEntry));
  2200. { Only include first hdrsym stab }
  2201. if hstab.ntype=0 then
  2202. skipstab:=true;
  2203. if skipfun then
  2204. begin
  2205. { Skip all stabs for function body until N_RBRAC }
  2206. skipfun:=hstab.ntype<>N_RBRAC;
  2207. skipstab:=true;
  2208. end;
  2209. if not skipstab then
  2210. begin
  2211. { Find corresponding Relocation }
  2212. currstabreloc:=nil;
  2213. while (currstabrelocidx<longword(currstabsec.ObjRelocations.Count)) do
  2214. begin
  2215. currstabreloc:=TObjRelocation(currstabsec.ObjRelocations[currstabrelocidx]);
  2216. if assigned(currstabreloc) and
  2217. (currstabreloc.dataoffset>=longword(j)*sizeof(TObjStabEntry)+stabrelocofs) then
  2218. break;
  2219. inc(currstabrelocidx);
  2220. end;
  2221. if assigned(currstabreloc) and
  2222. (currstabreloc.dataoffset=longword(j)*sizeof(TObjStabEntry)+stabrelocofs) then
  2223. begin
  2224. hstabReloc:=currstabReloc;
  2225. inc(currstabrelocidx);
  2226. end;
  2227. { Check if the stab is refering to a removed section }
  2228. if assigned(hstabreloc) then
  2229. begin
  2230. if assigned(hstabreloc.Symbol) then
  2231. relocsec:=hstabreloc.Symbol.ObjSection
  2232. else
  2233. relocsec:=hstabreloc.ObjSection;
  2234. if not assigned(relocsec) then
  2235. internalerror(200603302);
  2236. if not relocsec.Used then
  2237. begin
  2238. skipstab:=true;
  2239. if (hstab.ntype=N_Function) and (hstab.strpos<>0) then
  2240. begin
  2241. currstabstrsec.Data.seek(hstab.strpos);
  2242. bufsize:=currstabstrsec.Data.read(buf,sizeof(buf));
  2243. bufend:=indexbyte(buf,bufsize,Ord(':'));
  2244. if (bufend<>-1) and (bufend<bufsize-1) and (buf[bufend+1]=Ord('F')) then
  2245. skipfun:=true;
  2246. end;
  2247. end;
  2248. end;
  2249. end;
  2250. if not skipstab then
  2251. begin
  2252. { Copy string in stabstr }
  2253. if hstab.strpos<>0 then
  2254. begin
  2255. currstabstrsec.Data.seek(hstab.strpos);
  2256. hstab.strpos:=mergedstabstrsec.Size;
  2257. repeat
  2258. bufsize:=currstabstrsec.Data.read(buf,sizeof(buf));
  2259. bufend:=indexbyte(buf,bufsize,0);
  2260. if bufend=-1 then
  2261. bufend:=bufsize
  2262. else
  2263. begin
  2264. { include the #0 }
  2265. inc(bufend);
  2266. end;
  2267. mergedstabstrsec.write(buf,bufend);
  2268. until (buf[bufend-1]=0) or (bufsize<sizeof(buf));
  2269. end;
  2270. { Copy and Update the relocation }
  2271. if assigned(hstabreloc) then
  2272. begin
  2273. hstabreloc.Dataoffset:=mergestabcnt*sizeof(TObjStabEntry)+stabRelocofs;
  2274. { Remove from List without freeing the object }
  2275. currstabsec.ObjRelocations.List[currstabrelocidx-1]:=nil;
  2276. mergedstabsec.ObjRelocations.Add(hstabreloc);
  2277. end;
  2278. { Write updated stab }
  2279. mergedstabsec.write(hstab,sizeof(hstab));
  2280. inc(mergestabcnt);
  2281. end;
  2282. end;
  2283. end;
  2284. { Unload stabs }
  2285. if assigned(currstabstrsec) then
  2286. begin
  2287. currstabstrsec.Used:=False;
  2288. currstabstrsec.ReleaseData;
  2289. end;
  2290. currstabsec.Used:=false;
  2291. currstabsec.ReleaseData;
  2292. end;
  2293. { Generate new HdrSym }
  2294. if mergedstabsec.Size>0 then
  2295. begin
  2296. hstab.strpos:=1;
  2297. hstab.ntype:=0;
  2298. hstab.nother:=0;
  2299. hstab.ndesc:=word(mergestabcnt-1);
  2300. hstab.nvalue:=mergedstabstrsec.Size;
  2301. mergedstabsec.Data.seek(0);
  2302. mergedstabsec.Data.write(hstab,sizeof(hstab));
  2303. end;
  2304. { Replace all sections with our combined stabsec }
  2305. stabexesec.ObjSectionList.Clear;
  2306. stabstrexesec.ObjSectionList.Clear;
  2307. stabexesec.AddObjSection(mergedstabsec);
  2308. stabstrexesec.AddObjSection(mergedstabstrsec);
  2309. end;
  2310. procedure TExeOutput.RemoveEmptySections;
  2311. var
  2312. i, j : longint;
  2313. exesec : TExeSection;
  2314. doremove : boolean;
  2315. begin
  2316. for i:=0 to ExeSectionList.Count-1 do
  2317. begin
  2318. exesec:=TExeSection(ExeSectionList[i]);
  2319. doremove:=not(oso_keep in exesec.SecOptions) and
  2320. (
  2321. (exesec.ObjSectionlist.count=0) or
  2322. (
  2323. (cs_link_strip in current_settings.globalswitches) and
  2324. not(cs_link_separate_dbg_file in current_settings.globalswitches) and
  2325. (oso_debug in exesec.SecOptions)
  2326. )
  2327. );
  2328. if not doremove then
  2329. begin
  2330. { Check if section has no actual data }
  2331. doremove:=true;
  2332. for j:=0 to exesec.ObjSectionList.Count-1 do
  2333. if TObjSection(exesec.ObjSectionList[j]).Size<>0 then
  2334. begin
  2335. doremove:=false;
  2336. break;
  2337. end;
  2338. end;
  2339. if doremove and not (RelocSection and (exesec.Name='.reloc')) then
  2340. begin
  2341. Comment(V_Debug,'Deleting empty section '+exesec.name);
  2342. ExeSectionList[i]:=nil;
  2343. end;
  2344. end;
  2345. ExeSectionList.Pack;
  2346. end;
  2347. procedure TExeOutput.RemoveDebugInfo;
  2348. var
  2349. i : longint;
  2350. exesec : TExeSection;
  2351. begin
  2352. for i:=0 to ExeSectionList.Count-1 do
  2353. begin
  2354. exesec:=TExeSection(ExeSectionList[i]);
  2355. if (oso_debug in exesec.SecOptions) then
  2356. ExeSectionList[i]:=nil;
  2357. end;
  2358. ExeSectionList.Pack;
  2359. end;
  2360. procedure TExeOutput.RemoveUnreferencedSections;
  2361. var
  2362. ObjSectionWorkList : TFPObjectList;
  2363. procedure AddToObjSectionWorkList(aobjsec:TObjSection);
  2364. begin
  2365. if not aobjsec.Used then
  2366. begin
  2367. aobjsec.Used:=true;
  2368. ObjSectionWorkList.Add(aobjsec);
  2369. end;
  2370. end;
  2371. procedure DoReloc(objreloc:TObjRelocation);
  2372. var
  2373. objsym : TObjSymbol;
  2374. refobjsec : TObjSection;
  2375. begin
  2376. { Disabled Relocation to 0 }
  2377. if objreloc.typ=RELOC_ZERO then
  2378. exit;
  2379. if assigned(objreloc.symbol) then
  2380. begin
  2381. objsym:=objreloc.symbol;
  2382. if objsym.bind<>AB_LOCAL then
  2383. begin
  2384. if not(assigned(objsym.exesymbol) and
  2385. (objsym.exesymbol.State=symstate_defined)) then
  2386. internalerror(200603063);
  2387. objsym:=objsym.exesymbol.objsymbol;
  2388. end;
  2389. if not assigned(objsym.objsection) then
  2390. internalerror(200603062);
  2391. refobjsec:=objsym.objsection;
  2392. end
  2393. else
  2394. if assigned(objreloc.objsection) then
  2395. refobjsec:=objreloc.objsection
  2396. else
  2397. internalerror(200603316);
  2398. if assigned(exemap) then
  2399. begin
  2400. objsym:=objreloc.symbol;
  2401. if assigned(objsym) then
  2402. exemap.Add(' References '+objsym.name+' in '
  2403. +refobjsec.fullname)
  2404. else
  2405. exemap.Add(' References '+refobjsec.fullname);
  2406. end;
  2407. AddToObjSectionWorkList(refobjsec);
  2408. end;
  2409. procedure DoVTableRef(vtable:TExeVTable;VTableIdx:longint);
  2410. var
  2411. i : longint;
  2412. objreloc : TObjRelocation;
  2413. begin
  2414. objreloc:=vtable.VTableRef(VTableIdx);
  2415. if assigned(objreloc) then
  2416. begin
  2417. { Process the relocation now if the ObjSection is
  2418. already processed and marked as used. Otherwise we leave it
  2419. unprocessed. It'll then be resolved when the ObjSection is
  2420. changed to Used }
  2421. if vtable.ExeSymbol.ObjSymbol.ObjSection.Used then
  2422. DoReloc(objreloc);
  2423. end;
  2424. { This recursive walking is done here instead of
  2425. in TExeVTable.VTableRef because we can now process
  2426. all needed relocations }
  2427. for i:=0 to vtable.ChildList.Count-1 do
  2428. DoVTableRef(TExeVTable(vtable.ChildList[i]),VTableIdx);
  2429. end;
  2430. var
  2431. hs : string;
  2432. i,j,k : longint;
  2433. exesec : TExeSection;
  2434. objdata : TObjData;
  2435. objsec : TObjSection;
  2436. objsym : TObjSymbol;
  2437. code : integer;
  2438. vtableidx : longint;
  2439. vtableexesym : TExeSymbol;
  2440. begin
  2441. ObjSectionWorkList:=TFPObjectList.Create(false);
  2442. if assigned(exemap) then
  2443. exemap.AddHeader('Removing unreferenced sections');
  2444. { Initialize by marking all sections unused and
  2445. adding the sections with oso_keep flags to the ObjSectionWorkList }
  2446. for i:=0 to ObjDataList.Count-1 do
  2447. begin
  2448. ObjData:=TObjData(ObjDataList[i]);
  2449. for j:=0 to ObjData.ObjSectionList.Count-1 do
  2450. begin
  2451. objsec:=TObjSection(ObjData.ObjSectionList[j]);
  2452. objsec.Used:=false;
  2453. { TODO: remove debug section always keep}
  2454. if oso_debug in objsec.secoptions then
  2455. objsec.Used:=true;
  2456. if (oso_keep in objsec.secoptions) then
  2457. begin
  2458. AddToObjSectionWorkList(objsec);
  2459. if objsec.name='.fpc.n_links' then
  2460. objsec.Used:=false;
  2461. end;
  2462. end;
  2463. end;
  2464. AddToObjSectionWorkList(entrysym.exesymbol.objsymbol.objsection);
  2465. { Process all sections, add new sections to process based
  2466. on the symbol references }
  2467. while ObjSectionWorkList.Count>0 do
  2468. begin
  2469. objsec:=TObjSection(ObjSectionWorkList.Last);
  2470. if assigned(exemap) then
  2471. exemap.Add('Keeping '+objsec.FullName+' '+ToStr(objsec.ObjRelocations.Count)+' references');
  2472. ObjSectionWorkList.Delete(ObjSectionWorkList.Count-1);
  2473. { Process Relocations }
  2474. for i:=0 to objsec.ObjRelocations.count-1 do
  2475. DoReloc(TObjRelocation(objsec.ObjRelocations[i]));
  2476. { Process Virtual Entry calls }
  2477. if cs_link_opt_vtable in current_settings.globalswitches then
  2478. begin
  2479. for i:=0 to objsec.VTRefList.count-1 do
  2480. begin
  2481. objsym:=TObjSymbol(objsec.VTRefList[i]);
  2482. hs:=objsym.name;
  2483. Delete(hs,1,Pos('_',hs));
  2484. k:=Pos('$$',hs);
  2485. if k=0 then
  2486. internalerror(200603314);
  2487. vtableexesym:=texesymbol(FExeSymbolList.Find(Copy(hs,1,k-1)));
  2488. val(Copy(hs,k+2,length(hs)-k-1),vtableidx,code);
  2489. if (code<>0) then
  2490. internalerror(200603317);
  2491. if not assigned(vtableexesym) then
  2492. internalerror(200603315);
  2493. if not assigned(vtableexesym.vtable) then
  2494. internalerror(200603316);
  2495. DoVTableRef(vtableexesym.vtable,vtableidx);
  2496. end;
  2497. end;
  2498. end;
  2499. ObjSectionWorkList.Free;
  2500. ObjSectionWorkList:=nil;
  2501. { Remove unused objsections from ExeSectionList }
  2502. for i:=0 to ExeSectionList.Count-1 do
  2503. begin
  2504. exesec:=TExeSection(ExeSectionList[i]);
  2505. for j:=0 to exesec.ObjSectionlist.count-1 do
  2506. begin
  2507. objsec:=TObjSection(exesec.ObjSectionlist[j]);
  2508. if not objsec.used then
  2509. begin
  2510. if assigned(exemap) then
  2511. exemap.Add('Removing '+objsec.FullName);
  2512. exesec.ObjSectionlist[j]:=nil;
  2513. objsec.ReleaseData;
  2514. end;
  2515. end;
  2516. exesec.ObjSectionlist.Pack;
  2517. end;
  2518. end;
  2519. procedure TExeOutput.FixupRelocations;
  2520. var
  2521. i,j : longint;
  2522. exesec : TExeSection;
  2523. objsec : TObjSection;
  2524. begin
  2525. for i:=0 to ExeSectionList.Count-1 do
  2526. begin
  2527. exesec:=TExeSection(ExeSectionList[i]);
  2528. if not assigned(exesec) then
  2529. continue;
  2530. for j:=0 to exesec.ObjSectionlist.count-1 do
  2531. begin
  2532. objsec:=TObjSection(exesec.ObjSectionlist[j]);
  2533. if not objsec.Used then
  2534. internalerror(200603301);
  2535. objsec.FixupRelocs(Self);
  2536. end;
  2537. end;
  2538. end;
  2539. procedure TExeOutput.SetCurrMemPos(const AValue: qword);
  2540. begin
  2541. if AValue>MaxMemPos then
  2542. Message1(link_f_executable_too_big, target_os_string);
  2543. FCurrMemPos:=AValue;
  2544. end;
  2545. procedure TExeOutput.WriteExeSectionContent;
  2546. var
  2547. exesec : TExeSection;
  2548. objsec : TObjSection;
  2549. i,j : longint;
  2550. begin
  2551. for j:=0 to ExeSectionList.Count-1 do
  2552. begin
  2553. exesec:=TExeSection(ExeSectionList[j]);
  2554. { don't write normal section if writing only debug info }
  2555. if (ExeWriteMode=ewm_dbgonly) and
  2556. not(oso_debug in exesec.SecOptions) then
  2557. continue;
  2558. if oso_data in exesec.SecOptions then
  2559. begin
  2560. FWriter.Writezeros(Align(FWriter.Size,SectionDataAlign)-FWriter.Size);
  2561. for i:=0 to exesec.ObjSectionList.Count-1 do
  2562. begin
  2563. objsec:=TObjSection(exesec.ObjSectionList[i]);
  2564. if oso_data in objsec.secoptions then
  2565. begin
  2566. if not assigned(objsec.data) then
  2567. internalerror(200603042);
  2568. FWriter.writezeros(objsec.dataalignbytes);
  2569. if objsec.DataPos<>FWriter.Size then
  2570. internalerror(200602251);
  2571. FWriter.writearray(objsec.data);
  2572. end;
  2573. end;
  2574. end;
  2575. end;
  2576. end;
  2577. {****************************************************************************
  2578. TObjInput
  2579. ****************************************************************************}
  2580. constructor TObjInput.create;
  2581. begin
  2582. end;
  2583. destructor TObjInput.destroy;
  2584. begin
  2585. inherited destroy;
  2586. end;
  2587. function TObjInput.newObjData(const n:string):TObjData;
  2588. begin
  2589. result:=CObjData.create(n);
  2590. end;
  2591. procedure TObjInput.inputerror(const s : string);
  2592. begin
  2593. Comment(V_Error,s+' while reading '+InputFileName);
  2594. end;
  2595. procedure TObjInput.ReadSectionContent(Data:TObjData);
  2596. var
  2597. i: longint;
  2598. sec: TObjSection;
  2599. begin
  2600. for i:=0 to Data.ObjSectionList.Count-1 do
  2601. begin
  2602. sec:=TObjSection(Data.ObjSectionList[i]);
  2603. { Skip debug sections }
  2604. if (oso_debug in sec.SecOptions) and
  2605. (cs_link_strip in current_settings.globalswitches) and
  2606. not(cs_link_separate_dbg_file in current_settings.globalswitches) then
  2607. continue;
  2608. if assigned(sec.Data) then
  2609. begin
  2610. FReader.Seek(sec.datapos);
  2611. if not FReader.ReadArray(sec.data,sec.Size) then
  2612. begin
  2613. InputError('Can''t read object data');
  2614. exit;
  2615. end;
  2616. end;
  2617. end;
  2618. end;
  2619. {$ifdef MEMDEBUG}
  2620. initialization
  2621. memobjsymbols:=TMemDebug.create('ObjSymbols');
  2622. memobjsymbols.stop;
  2623. memobjsections:=TMemDebug.create('ObjSections');
  2624. memobjsections.stop;
  2625. finalization
  2626. memobjsymbols.free;
  2627. memobjsections.free;
  2628. {$endif MEMDEBUG}
  2629. end.