1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
|
{
This file is part of the Free Pascal run time library.
Copyright (c) 2008 by Giulio Bernardi
Resource reader for Mach-O files
See the file COPYING.FPC, included in this distribution,
for details about the copyright.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
**********************************************************************}
type
{ _TMachOSubReader_ }
_TMachOSubReader_ = class(TAbstractMachOSubReader)
private
fSection : _TSection_;
fResHdr : _TResHdr_;
function FindResSection(aStream : TStream) : boolean;
procedure ReadResHeader(aStream : TStream);
protected
procedure Load(aResources : TResources; aStream : TStream); override;
procedure ReadNode(aStream : TStream; aParent : TResourceTreeNode;
aResources : TResources; named : boolean); override;
public
constructor Create(aParent : TMachOResourceReader; const aHeader : TMachHdr;
const aOppositeEndianess : boolean); override;
end;
{ _TMachOSubReader_ }
procedure _TMachOSubReader_.ReadNode(aStream: TStream;
aParent: TResourceTreeNode; aResources: TResources; named: boolean);
var infonode : _TResInfoNode_;
aNode : TResourceTreeNode;
i : integer;
oldpos : int64;
desc : TResourceDesc;
begin
aStream.ReadBuffer(infonode,sizeof(infonode));
oldpos:=aStream.Position;
if fOppositeEndianess then
begin
infonode.nameid:=SwapEndian(infonode.nameid);
infonode.ncount:=SwapEndian(infonode.ncount);
infonode.idcountsize:=SwapEndian(infonode.idcountsize);
infonode.subptr:=SwapEndian(infonode.subptr);
end;
if aParent=nil then aNode:=fRoot
else
begin
desc:=TResourceDesc.Create;
try
if named then desc.Name:=ReadString(aStream,
fSection.offset+infonode.nameid-fSection.addr)
else desc.ID:=infonode.nameid;
aNode:=aParent.CreateSubNode(desc);
finally
desc.Free;
end;
end;
aStream.Position:=fSection.offset+infonode.subptr-fSection.addr;
if aNode.IsLeaf then
ReadResData(aStream,aNode,aResources,infonode.idcountsize)
else
begin
for i:=1 to infonode.ncount do
ReadNode(aStream,aNode,aResources,true);
for i:=1 to infonode.idcountsize do
ReadNode(aStream,aNode,aResources,false);
end;
aStream.Position:=oldpos;
end;
function _TMachOSubReader_.FindResSection(aStream: TStream) : boolean;
var i,j : integer;
lc : TLoadCommand;
seg : _TSegmentCommand_;
nextpos : int64;
begin
for i:=1 to fHeader.ncmds do
begin
aStream.ReadBuffer(lc,sizeof(lc));
if fOppositeEndianess then
begin
lc.cmd:=SwapEndian(lc.cmd);
lc.cmdsize:=SwapEndian(lc.cmdsize);
end;
nextpos:=aStream.Position-sizeof(lc)+lc.cmdsize;
if lc.cmdsize=0 then break;
if lc.cmd=fSegType then
begin
aStream.ReadBuffer(seg,sizeof(seg));
if fOppositeEndianess then
seg.nsects:=SwapEndian(seg.nsects);
for j:=1 to seg.nsects do
begin
aStream.ReadBuffer(fSection,sizeof(fSection));
if (fSection.segname=DataSegName) and (fSection.sectname=RsrcSectName) then
begin
if fOppositeEndianess then
begin
fSection.addr:=SwapEndian(fSection.addr);
fSection.size:=SwapEndian(fSection.size);
fSection.offset:=SwapEndian(fSection.offset);
fSection.align:=SwapEndian(fSection.align);
fSection.reloff:=SwapEndian(fSection.reloff);
fSection.nreloc:=SwapEndian(fSection.nreloc);
fSection.flags:=SwapEndian(fSection.flags);
fSection.reserved1:=SwapEndian(fSection.reserved1);
fSection.reserved2:=SwapEndian(fSection.reserved2);
end;
Result:=true;
exit;
end;
end;
end;
aStream.Position:=nextpos;
end;
//nothing found
Result:=false;
FillByte(fSection,sizeof(fSection),0);
end;
procedure _TMachOSubReader_.ReadResHeader(aStream: TStream);
begin
aStream.Position:=fSection.offset;
aStream.ReadBuffer(fResHdr,sizeof(fResHdr));
if fOppositeEndianess then
begin
fResHdr.rootptr:=SwapEndian(fResHdr.rootptr);
fResHdr.count:=SwapEndian(fResHdr.count);
end;
aStream.Position:=fSection.offset+fResHdr.rootptr-fSection.addr;
end;
procedure _TMachOSubReader_.Load(aResources: TResources; aStream: TStream);
begin
if not FindResSection(aStream) then exit;
ReadResHeader(aStream);
if fResHdr.count=0 then exit; //no resources in this file
LoadResources(aResources,aStream);
end;
constructor _TMachOSubReader_.Create(aParent : TMachOResourceReader;
const aHeader : TMachHdr; const aOppositeEndianess : boolean);
begin
inherited Create(aParent,aHeader,aOppositeEndianess);
{$IF _TMachOSubReader_=TMachO32SubReader}
fSegType:=LC_SEGMENT;
{$ELSE}
fSegType:=LC_SEGMENT_64;
{$ENDIF}
end;
|