elfwriter.pp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625
  1. {
  2. This file is part of the Free Pascal run time library.
  3. Copyright (c) 2008 by Giulio Bernardi
  4. Resource writer for ELF files
  5. See the file COPYING.FPC, included in this distribution,
  6. for details about the copyright.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. **********************************************************************}
  11. unit elfwriter;
  12. {$MODE OBJFPC} {$H+}
  13. interface
  14. uses
  15. Classes, SysUtils, resource, elfconsts, elftypes;
  16. type
  17. EElfResourceWriterException = class(EResourceWriterException);
  18. EElfResourceWriterUnknownMachineException = class(EElfResourceWriterException);
  19. EElfResourceWriterUnknownClassException = class(EElfResourceWriterException);
  20. EElfResourceWriterUnknownSectionException = class(EElfResourceWriterException);
  21. type
  22. { TElfResourceWriter }
  23. TElfResourceWriter = class (TAbstractResourceWriter)
  24. private
  25. fExtensions : string;
  26. fDescription : string;
  27. fMachineTypeInt : integer;
  28. fMachineType : TElfMachineType;
  29. fOrder : byte;
  30. fBits : byte;
  31. fNativeOrder : integer;
  32. fOppositeEndianess : boolean;
  33. procedure SetDefaultTarget;
  34. procedure SetMachineType(const aMachineType : TElfMachineType);
  35. procedure WriteElfIdent(aStream : TStream);
  36. protected
  37. function GetExtensions : string; override;
  38. function GetDescription : string; override;
  39. procedure Write(aResources : TResources; aStream : TStream); override;
  40. public
  41. constructor Create; override;
  42. destructor Destroy; override;
  43. property MachineType : TElfMachineType read fMachineType write SetMachineType;
  44. end;
  45. implementation
  46. uses resourcetree, strtable, fpcrestypes;
  47. type
  48. { TElfSections }
  49. TElfSections = class
  50. private
  51. fList : TFPList;
  52. fStringTable : TObjectStringTable;
  53. function GetCount : integer;
  54. function GetItem(index : integer) : PElf64SectHdr;
  55. protected
  56. public
  57. constructor Create(aStringTable : TObjectStringTable);
  58. destructor Destroy; override;
  59. function Add(const aName: string; const aType, aFlags : longword;
  60. const aOffset, aSize : qword; const aAddrAlign : longword) : integer; overload;
  61. function Add(const aName: string; const aType, aFlags : longword;
  62. const aOffset, aSize, aEntSize : qword; const aLink, aInfo,aAddrAlign
  63. : longword) : integer; overload;
  64. procedure Clear;
  65. property Count : integer read GetCount;
  66. property Items[index : integer] : PElf64SectHdr read GetItem; default;
  67. end;
  68. { TElfSymbolTable }
  69. TElfSymbolTable = class
  70. private
  71. fList : TFPList;
  72. fSectFree : integer;
  73. fLocFree : integer;
  74. fStringTable : TObjectStringTable;
  75. function CreateSym(const aName : string; const aValue, aSize : qword;
  76. const aBind, aType : byte; const aSectIdx : integer) : PElf64Symbol;
  77. procedure Clear;
  78. function GetCount : integer;
  79. function GetItem(index : integer) : PElf64Symbol;
  80. protected
  81. public
  82. constructor Create(aStringTable : TObjectStringTable);
  83. destructor Destroy; override;
  84. procedure AddSection(const aSectIdx : integer);
  85. procedure AddLocal(const aName : string; const aValue, aSize : qword;
  86. const aType : byte; const aSectIdx : integer);
  87. procedure AddGlobal(const aName : string; const aValue, aSize : qword;
  88. const aType : byte; const aSectIdx : integer);
  89. property Count : integer read GetCount;
  90. property Items[index : integer] : PElf64Symbol read GetItem; default;
  91. property FirstGlobal : integer read fLocFree;
  92. end;
  93. { TAbstractElfSubWriter }
  94. TAbstractElfSubWriter = class
  95. private
  96. protected
  97. fParent : TElfResourceWriter;
  98. fOppositeEndianess : boolean;
  99. fMachineType : integer;
  100. fDataAlignment : longword;
  101. fMachineFlags : longword;
  102. fRoot : TRootResTreeNode;
  103. fSectStringTable : TObjectStringTable;
  104. fSymStringTable : TObjectStringTable;
  105. fResStringTable : TResStringTable;
  106. fSymbolTable : TElfSymbolTable;
  107. fSections : TElfSections;
  108. fShStrTabIdx : integer;
  109. fSymStrTabIdx : integer;
  110. fSymTabIdx : integer;
  111. fSectHdrOffset : qword;
  112. fCurOfs : longword;
  113. fDataCurOfs : longword;
  114. fSectionStart : qword;
  115. procedure Align(aBound : integer; aStream : TStream);
  116. function NextAligned(aBound, aValue : longword) : longword;
  117. procedure PrescanResourceTree; virtual; abstract;
  118. function PrescanNode(aNode : TResourceTreeNode; aNodeSize : longword) : longword;
  119. procedure WriteNodeInfo(aStream : TStream; aNode : TResourceTreeNode); virtual; abstract;
  120. procedure WriteSubNodes(aStream : TStream; aNode : TResourceTreeNode);
  121. procedure WriteResStringTable(aStream : TStream);
  122. procedure WriteRawData(aStream : TStream);
  123. procedure WriteResData(aStream : TStream; aNode : TResourceTreeNode);
  124. procedure AddEmptySections(aResources : TResources; aStream : TStream);
  125. procedure WriteStrTab(aStream : TStream);
  126. procedure WriteShStrTab(aStream : TStream);
  127. procedure Write(aResources : TResources; aStream : TStream); virtual; abstract;
  128. public
  129. constructor Create(aParent : TElfResourceWriter; const aMachineType : integer;
  130. const aOppositeEndianess : boolean); virtual;
  131. destructor Destroy; override;
  132. end;
  133. type
  134. TElfRelocInfo = record
  135. RelocType : longword;
  136. SectionType : integer;
  137. end;
  138. (*
  139. Almost all differences in 32 and 64 bit elf files lie in record sizes.
  140. Generics don't work with record types, so use macros to do this task
  141. (uglier, but should be the same)
  142. *)
  143. {$MACRO ON}
  144. //Define TElf32RelocTable and TElf32SubWriter
  145. {$DEFINE _TElfRelocTable_:=TElf32RelocTable}
  146. {$DEFINE _TPElfRela_:=PElf32Rela}
  147. {$DEFINE _TElfRela_:=TElf32Rela}
  148. {$DEFINE _TPElfRel_:=PElf32Rel}
  149. {$DEFINE _TElfRel_:=TElf32Rel}
  150. {$DEFINE _Tword_:=longword}
  151. {$DEFINE _TElfSubWriter_:=TElf32SubWriter}
  152. {$DEFINE _TElfHdr_:=TElf32Hdr}
  153. {$DEFINE _TElfSectHdr_:=TElf32SectHdr}
  154. {$DEFINE _TElfSymbol_:=TElf32Symbol}
  155. {$DEFINE _TResHdr_:=TResHdr32}
  156. {$DEFINE _TResInfoNode_:=TResInfoNode32}
  157. {$INCLUDE elfsubwriter.inc}
  158. //Define TElf64RelocTable and TElf32SubWriter
  159. {$DEFINE _TElfRelocTable_:=TElf64RelocTable}
  160. {$DEFINE _TPElfRela_:=PElf64Rela}
  161. {$DEFINE _TElfRela_:=TElf64Rela}
  162. {$DEFINE _TPElfRel_:=PElf64Rel}
  163. {$DEFINE _TElfRel_:=TElf64Rel}
  164. {$DEFINE _Tword_:=qword}
  165. {$DEFINE _TElfSubWriter_:=TElf64SubWriter}
  166. {$DEFINE _TElfHdr_:=TElf64Hdr}
  167. {$DEFINE _TElfSectHdr_:=TElf64SectHdr}
  168. {$DEFINE _TElfSymbol_:=TElf64Symbol}
  169. {$DEFINE _TResHdr_:=TResHdr64}
  170. {$DEFINE _TResInfoNode_:=TResInfoNode64}
  171. {$INCLUDE elfsubwriter.inc}
  172. //Clean all this stuff...
  173. {$UNDEF _TElfRelocTable_}
  174. {$UNDEF _TPElfRela_}
  175. {$UNDEF _TElfRela_}
  176. {$UNDEF _TPElfRel_}
  177. {$UNDEF _TElfRel_}
  178. {$UNDEF _Tword_}
  179. {$UNDEF _TElfSubWriter_}
  180. {$UNDEF _TElfHdr_}
  181. {$UNDEF _TElfSectHdr_}
  182. {$UNDEF _TElfSymbol_}
  183. {$UNDEF _TResHdr_}
  184. {$UNDEF _TResInfoNode_}
  185. { TElfSections }
  186. function TElfSections.GetCount: integer;
  187. begin
  188. Result:=fList.Count;
  189. end;
  190. function TElfSections.GetItem(index: integer): PElf64SectHdr;
  191. begin
  192. Result:=PElf64SectHdr(fList[index]);
  193. end;
  194. constructor TElfSections.Create(aStringTable : TObjectStringTable);
  195. begin
  196. fList:=TFPList.Create;
  197. fStringTable:=aStringTable;
  198. Add('',0,0,0,0,0); //empty section
  199. end;
  200. destructor TElfSections.Destroy;
  201. var i : integer;
  202. p : PElf64SectHdr;
  203. begin
  204. for i:=0 to fList.Count-1 do
  205. begin
  206. p:=PElf64SectHdr(fList[i]);
  207. FreeMem(p);
  208. end;
  209. fList.Free;
  210. end;
  211. function TElfSections.Add(const aName: string; const aType, aFlags : longword;
  212. const aOffset, aSize : qword; const aAddrAlign : longword) : integer;
  213. begin
  214. Result:=Add(aName,aType,aFlags,aOffset,aSize,0,0,0,aAddrAlign);
  215. end;
  216. function TElfSections.Add(const aName: string; const aType, aFlags: longword;
  217. const aOffset, aSize, aEntSize: qword; const aLink, aInfo, aAddrAlign: longword): integer;
  218. var p : PElf64SectHdr;
  219. begin
  220. Result:=fList.Count;
  221. p:=GetMem(sizeof(TElf64SectHdr));
  222. p^.NameIdx:=fStringTable.Add(aName);
  223. p^._Type:=aType;
  224. p^.Flags:=aFlags;
  225. p^.Address:=0;
  226. p^.Offset:=aOffset;;
  227. p^.Size:=aSize;
  228. p^.Link:=aLink;
  229. p^.Info:=aInfo;
  230. p^.AddrAlign:=aAddrAlign;
  231. p^.EntSize:=aEntSize;
  232. fList.Add(p);
  233. end;
  234. procedure TElfSections.Clear;
  235. var i : integer;
  236. p, first : PElf64SectHdr;
  237. begin
  238. first:=PElf64SectHdr(fList[0]);
  239. for i:=1 to fList.Count-1 do
  240. begin
  241. p:=PElf64SectHdr(fList[i]);
  242. FreeMem(p);
  243. end;
  244. fList.Clear;
  245. fList.Add(first);
  246. end;
  247. { TElfSymbolTable }
  248. constructor TElfSymbolTable.Create(aStringTable: TObjectStringTable);
  249. var p : PElf64Symbol;
  250. begin
  251. fList:=TFPList.Create;
  252. fStringTable:=aStringTable;
  253. p:=CreateSym('',0,0,0,0,0);
  254. fList.Add(p);
  255. fSectFree:=1;
  256. fLocFree:=1;
  257. end;
  258. destructor TElfSymbolTable.Destroy;
  259. begin
  260. Clear;
  261. fList.Free;
  262. end;
  263. procedure TElfSymbolTable.AddSection(const aSectIdx: integer);
  264. var p : PElf64Symbol;
  265. begin
  266. p:=CreateSym('',0,0,STB_LOCAL,STT_SECTION,aSectIdx);
  267. if fSectFree=fList.Count then
  268. fList.Add(p)
  269. else
  270. fList.Insert(fSectFree,p);
  271. inc(fSectFree);
  272. inc(fLocFree);
  273. end;
  274. procedure TElfSymbolTable.AddLocal(const aName: string; const aValue,
  275. aSize: qword; const aType: byte; const aSectIdx: integer);
  276. var p : PElf64Symbol;
  277. begin
  278. p:=CreateSym(aName,aValue,aSize,STB_LOCAL,aType,aSectIdx);
  279. if fLocFree=fList.Count then
  280. fList.Add(p)
  281. else
  282. fList.Insert(fLocFree,p);
  283. inc(fLocFree);
  284. end;
  285. procedure TElfSymbolTable.AddGlobal(const aName: string; const aValue,
  286. aSize: qword; const aType: byte; const aSectIdx: integer);
  287. var p : PElf64Symbol;
  288. begin
  289. p:=CreateSym(aName,aValue,aSize,STB_GLOBAL,aType,aSectIdx);
  290. fList.Add(p)
  291. end;
  292. procedure TElfSymbolTable.Clear;
  293. var p : PElf64Symbol;
  294. i : integer;
  295. begin
  296. for i:=0 to fList.Count-1 do
  297. begin
  298. p:=PElf64Symbol(fList[i]);
  299. FreeMem(p);
  300. end;
  301. fList.Clear;
  302. end;
  303. function TElfSymbolTable.GetCount: integer;
  304. begin
  305. Result:=fList.Count;
  306. end;
  307. function TElfSymbolTable.GetItem(index: integer): PElf64Symbol;
  308. begin
  309. Result:=PElf64Symbol(fList[index]);
  310. end;
  311. function TElfSymbolTable.CreateSym(const aName : string; const aValue, aSize : qword;
  312. const aBind, aType : byte; const aSectIdx : integer) : PElf64Symbol;
  313. var p : PElf64Symbol;
  314. begin
  315. p:=GetMem(sizeof(TElf64Symbol));
  316. p^.Name:=fStringTable.Add(aName);
  317. p^.Value:=aValue;
  318. p^.Size:=aSize;
  319. p^.Info:=aBind shl 4;
  320. p^.Info:=p^.Info or (aType and $0F);
  321. p^.Other:=0;
  322. p^.SectIdx:=aSectIdx;
  323. Result:=p;
  324. end;
  325. { TAbstractElfSubWriter }
  326. procedure TAbstractElfSubWriter.Align(aBound : integer; aStream : TStream);
  327. var topad,tmp : integer;
  328. qw : qword;
  329. begin
  330. qw:=0;
  331. topad:=aBound-(aStream.Position mod aBound);
  332. if topad<>aBound then
  333. while topad>0 do
  334. begin
  335. if topad>8 then tmp:=8 else tmp:=topad;
  336. aStream.WriteBuffer(qw,tmp);
  337. dec(topad,tmp);
  338. end;
  339. end;
  340. function TAbstractElfSubWriter.NextAligned(aBound, aValue : longword) : longword;
  341. var topad : longword;
  342. begin
  343. Result:=aValue;
  344. topad:=aBound-(aValue mod aBound);
  345. if topad<>aBound then inc(Result,topad);
  346. end;
  347. function TAbstractElfSubWriter.PrescanNode(aNode: TResourceTreeNode;
  348. aNodeSize: longword): longword;
  349. var curofs : longword;
  350. i : integer;
  351. subnode : TResourceTreeNode;
  352. begin
  353. if aNode.IsLeaf then
  354. begin
  355. Result:=aNode.SubDirRVA;
  356. exit;
  357. end;
  358. if aNode.Desc.DescType=dtName then
  359. aNode.NameRVA:=fResStringTable.Add(aNode.Desc.Name);
  360. //first node subnodes begin at curofs (after all node headers)
  361. curofs:=aNode.SubDirRva+(aNode.NamedCount+aNode.IDCount)*aNodeSize;
  362. for i:=0 to aNode.NamedCount-1 do
  363. begin
  364. subnode:=aNode.NamedEntries[i];
  365. subnode.SubDirRVA:=curofs;
  366. curofs:=PrescanNode(subnode,aNodeSize);
  367. end;
  368. for i:=0 to aNode.IDCount-1 do
  369. begin
  370. subnode:=aNode.IDEntries[i];
  371. subnode.SubDirRVA:=curofs;
  372. curofs:=PrescanNode(subnode,aNodeSize);
  373. end;
  374. Result:=curofs;
  375. end;
  376. procedure TAbstractElfSubWriter.WriteSubNodes(aStream: TStream;
  377. aNode: TResourceTreeNode);
  378. var i : integer;
  379. begin
  380. for i:=0 to aNode.NamedCount-1 do
  381. WriteNodeInfo(aStream,aNode.NamedEntries[i]);
  382. for i:=0 to aNode.IDCount-1 do
  383. WriteNodeInfo(aStream,aNode.IDEntries[i]);
  384. for i:=0 to aNode.NamedCount-1 do
  385. WriteSubNodes(aStream,aNode.NamedEntries[i]);
  386. for i:=0 to aNode.IDCount-1 do
  387. WriteSubNodes(aStream,aNode.IDEntries[i]);
  388. end;
  389. procedure TAbstractElfSubWriter.WriteResStringTable(aStream: TStream);
  390. begin
  391. if fResStringTable.Used then
  392. fResStringTable.WriteToStream(aStream);
  393. Align(fDataAlignment,aStream);
  394. end;
  395. procedure TAbstractElfSubWriter.WriteRawData(aStream: TStream);
  396. begin
  397. WriteResData(aStream,fRoot);
  398. end;
  399. procedure TAbstractElfSubWriter.WriteResData(aStream: TStream;
  400. aNode: TResourceTreeNode);
  401. var rawdata : TStream;
  402. i : integer;
  403. begin
  404. if aNode.IsLeaf then
  405. begin
  406. rawdata:=aNode.Data.RawData;
  407. rawdata.Position:=0;
  408. aStream.CopyFrom(rawdata,rawdata.Size);
  409. Align(fDataAlignment,aStream);
  410. exit;
  411. end;
  412. for i:=0 to aNode.NamedCount-1 do
  413. WriteResData(aStream,aNode.NamedEntries[i]);
  414. for i:=0 to aNode.IDCount-1 do
  415. WriteResData(aStream,aNode.IDEntries[i]);
  416. end;
  417. procedure TAbstractElfSubWriter.AddEmptySections(aResources : TResources; aStream: TStream);
  418. begin
  419. Align(fDataAlignment,aStream);
  420. fSections.Add(HandlesSectName,SHT_NOBITS,SHF_ALLOC or SHF_WRITE,
  421. aStream.Position,fDataAlignment*aResources.Count,fDataAlignment);
  422. fSections.Add('.text',SHT_PROGBITS,SHF_ALLOC or SHF_EXECINSTR,aStream.Position,0,4);
  423. fSections.Add('.data',SHT_PROGBITS,SHF_ALLOC or SHF_WRITE,aStream.Position,0,4);
  424. fSections.Add('.bss', SHT_NOBITS,SHF_ALLOC or SHF_WRITE,aStream.Position,0,4);
  425. fSections.Add('.note.GNU-stack', SHT_PROGBITS,0,aStream.Position,0,1);
  426. end;
  427. procedure TAbstractElfSubWriter.WriteStrTab(aStream: TStream);
  428. begin
  429. fSymStrTabIdx:=fSections.Add('.strtab',SHT_STRTAB,0,aStream.Position,
  430. fSymStringTable.Size,1);
  431. fSymStringTable.WriteToStream(aStream);
  432. end;
  433. procedure TAbstractElfSubWriter.WriteShStrTab(aStream: TStream);
  434. const namelen = length('.shstrtab')+1;
  435. begin
  436. fShStrTabIdx:=fSections.Add('.shstrtab',SHT_STRTAB,0,aStream.Position,
  437. fSectStringTable.Size+namelen,1);
  438. fSectStringTable.WriteToStream(aStream);
  439. end;
  440. constructor TAbstractElfSubWriter.Create(aParent : TElfResourceWriter;
  441. const aMachineType: integer; const aOppositeEndianess: boolean);
  442. begin
  443. fMachineType:=aMachineType;
  444. fOppositeEndianess:=aOppositeEndianess;
  445. fRoot:=nil;
  446. fParent:=aParent;
  447. fSectStringTable:=TObjectStringTable.Create(nil,0);
  448. fSymStringTable:=TObjectStringTable.Create(nil,0);
  449. fResStringTable:=TResStringTable.Create;
  450. fSymbolTable:=TElfSymbolTable.Create(fSymStringTable);
  451. fSections:=TElfSections.Create(fSectStringTable);
  452. fShStrTabIdx:=0;
  453. fSymStrTabIdx:=0;
  454. fSectHdrOffset:=0;
  455. fCurOfs:=0;
  456. fDataCurOfs:=0;
  457. fSectionStart:=0;
  458. end;
  459. destructor TAbstractElfSubWriter.Destroy;
  460. begin
  461. fSectStringTable.Free;
  462. fSymStringTable.Free;
  463. fResStringTable.Free;
  464. fSymbolTable.Free;
  465. fSections.Free;
  466. end;
  467. { TElfResourceWriter }
  468. procedure TElfResourceWriter.SetDefaultTarget;
  469. begin
  470. {$INCLUDE elfdefaulttarget.inc}
  471. end;
  472. procedure TElfResourceWriter.SetMachineType(const aMachineType: TElfMachineType);
  473. begin
  474. case aMachineType of
  475. emtsparc : begin fMachineTypeInt:=EM_SPARC; fBits:=ELFCLASS32; fOrder:=ELFDATA2MSB; end;
  476. emti386 : begin fMachineTypeInt:=EM_386; fBits:=ELFCLASS32; fOrder:=ELFDATA2LSB; end;
  477. emtm68k : begin fMachineTypeInt:=EM_68K; fBits:=ELFCLASS32; fOrder:=ELFDATA2MSB; end;
  478. emtppc : begin fMachineTypeInt:=EM_PPC; fBits:=ELFCLASS32; fOrder:=ELFDATA2MSB; end;
  479. emtppc64 : begin fMachineTypeInt:=EM_PPC64; fBits:=ELFCLASS64;fOrder:=ELFDATA2MSB; end;
  480. emtppc64le: begin fMachineTypeInt:=EM_PPC64; fBits:=ELFCLASS64;fOrder:=ELFDATA2LSB; end;
  481. emtarm : begin fMachineTypeInt:=EM_ARM; fBits:=ELFCLASS32; fOrder:=ELFDATA2LSB; end;
  482. emtarmeb : begin fMachineTypeInt:=EM_ARM; fBits:=ELFCLASS32; fOrder:=ELFDATA2MSB; end;
  483. emtaarch64: begin fMachineTypeInt:=EM_AARCH64; fBits:=ELFCLASS64; fOrder:=ELFDATA2LSB; end;
  484. emtalpha : begin fMachineTypeInt:=EM_ALPHA; fBits:=ELFCLASS64; fOrder:=ELFDATA2LSB; end;
  485. emtia64 : begin fMachineTypeInt:=EM_IA_64; fBits:=ELFCLASS64; fOrder:=ELFDATA2LSB; end;
  486. emtx86_64 : begin fMachineTypeInt:=EM_X86_64; fBits:=ELFCLASS64; fOrder:=ELFDATA2LSB; end;
  487. emtmips : begin fMachineTypeInt:=EM_MIPS; fBits:=ELFCLASS32; fOrder:=ELFDATA2MSB; end;
  488. emtmipsel : begin fMachineTypeInt:=EM_MIPS; fBits:=ELFCLASS32; fOrder:=ELFDATA2LSB; end
  489. else
  490. raise EElfResourceWriterUnknownMachineException.Create('');
  491. end;
  492. fMachineType:=aMachineType;
  493. fOppositeEndianess:=fNativeOrder<>fOrder;
  494. end;
  495. procedure TElfResourceWriter.WriteElfIdent(aStream: TStream);
  496. var ident : TElfIdent;
  497. begin
  498. ident.Magic:=ELFMAGIC;
  499. ident.ElfClass:=fBits;
  500. ident.ElfData:=fOrder;
  501. ident.ElfVersion:=EV_CURRENT;
  502. ident.OsAbi:=ELFOSABI_NONE; // UNIX System V ABI
  503. ident.AbiVersion:=0;
  504. FillByte(ident.Padding[9],length(ident.Padding),0);
  505. aStream.WriteBuffer(ident,sizeof(ident));
  506. end;
  507. function TElfResourceWriter.GetExtensions: string;
  508. begin
  509. Result:=fExtensions;
  510. end;
  511. function TElfResourceWriter.GetDescription: string;
  512. begin
  513. Result:=fDescription;
  514. end;
  515. procedure TElfResourceWriter.Write(aResources: TResources; aStream: TStream);
  516. var subwriter : TAbstractElfSubWriter;
  517. begin
  518. WriteElfIdent(aStream);
  519. case fBits of
  520. ELFCLASS32 : subwriter:=TElf32SubWriter.Create(self,fMachineTypeInt,fOppositeEndianess);
  521. ELFCLASS64 : subwriter:=TElf64SubWriter.Create(self,fMachineTypeInt,fOppositeEndianess)
  522. else
  523. raise EElfResourceWriterUnknownClassException.Create('');
  524. end;
  525. try
  526. subwriter.Write(aResources,aStream);
  527. finally
  528. subwriter.Free;
  529. end;
  530. end;
  531. constructor TElfResourceWriter.Create;
  532. begin
  533. fExtensions:='.o .or';
  534. fDescription:='ELF resource writer';
  535. SetDefaultTarget;
  536. end;
  537. destructor TElfResourceWriter.Destroy;
  538. begin
  539. end;
  540. initialization
  541. TResources.RegisterWriter('.o',TElfResourceWriter);
  542. TResources.RegisterWriter('.or',TElfResourceWriter);
  543. end.