1*f6dc9357SAndroid Build Coastguard Worker // MachoHandler.cpp
2*f6dc9357SAndroid Build Coastguard Worker
3*f6dc9357SAndroid Build Coastguard Worker #include "StdAfx.h"
4*f6dc9357SAndroid Build Coastguard Worker
5*f6dc9357SAndroid Build Coastguard Worker #include "../../../C/CpuArch.h"
6*f6dc9357SAndroid Build Coastguard Worker
7*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/ComTry.h"
8*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/MyBuffer.h"
9*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/StringConvert.h"
10*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/IntToString.h"
11*f6dc9357SAndroid Build Coastguard Worker
12*f6dc9357SAndroid Build Coastguard Worker #include "../../Windows/PropVariantUtils.h"
13*f6dc9357SAndroid Build Coastguard Worker
14*f6dc9357SAndroid Build Coastguard Worker #include "../Common/LimitedStreams.h"
15*f6dc9357SAndroid Build Coastguard Worker #include "../Common/ProgressUtils.h"
16*f6dc9357SAndroid Build Coastguard Worker #include "../Common/RegisterArc.h"
17*f6dc9357SAndroid Build Coastguard Worker #include "../Common/StreamUtils.h"
18*f6dc9357SAndroid Build Coastguard Worker
19*f6dc9357SAndroid Build Coastguard Worker #include "../Compress/CopyCoder.h"
20*f6dc9357SAndroid Build Coastguard Worker
Get32(const Byte * p,bool be)21*f6dc9357SAndroid Build Coastguard Worker static UInt32 Get32(const Byte *p, bool be) { if (be) return GetBe32(p); return GetUi32(p); }
Get64(const Byte * p,bool be)22*f6dc9357SAndroid Build Coastguard Worker static UInt64 Get64(const Byte *p, bool be) { if (be) return GetBe64(p); return GetUi64(p); }
23*f6dc9357SAndroid Build Coastguard Worker
24*f6dc9357SAndroid Build Coastguard Worker using namespace NWindows;
25*f6dc9357SAndroid Build Coastguard Worker using namespace NCOM;
26*f6dc9357SAndroid Build Coastguard Worker
27*f6dc9357SAndroid Build Coastguard Worker namespace NArchive {
28*f6dc9357SAndroid Build Coastguard Worker namespace NMacho {
29*f6dc9357SAndroid Build Coastguard Worker
30*f6dc9357SAndroid Build Coastguard Worker #define CPU_ARCH_ABI64 (1 << 24)
31*f6dc9357SAndroid Build Coastguard Worker #define CPU_TYPE_386 7
32*f6dc9357SAndroid Build Coastguard Worker #define CPU_TYPE_ARM 12
33*f6dc9357SAndroid Build Coastguard Worker #define CPU_TYPE_SPARC 14
34*f6dc9357SAndroid Build Coastguard Worker #define CPU_TYPE_PPC 18
35*f6dc9357SAndroid Build Coastguard Worker
36*f6dc9357SAndroid Build Coastguard Worker #define CPU_SUBTYPE_I386_ALL 3
37*f6dc9357SAndroid Build Coastguard Worker
38*f6dc9357SAndroid Build Coastguard Worker // #define CPU_TYPE_PPC64 (CPU_ARCH_ABI64 | CPU_TYPE_PPC)
39*f6dc9357SAndroid Build Coastguard Worker #define CPU_TYPE_AMD64 (CPU_ARCH_ABI64 | CPU_TYPE_386)
40*f6dc9357SAndroid Build Coastguard Worker #define CPU_TYPE_ARM64 (CPU_ARCH_ABI64 | CPU_TYPE_ARM)
41*f6dc9357SAndroid Build Coastguard Worker
42*f6dc9357SAndroid Build Coastguard Worker #define CPU_SUBTYPE_LIB64 ((UInt32)1 << 31)
43*f6dc9357SAndroid Build Coastguard Worker
44*f6dc9357SAndroid Build Coastguard Worker #define CPU_SUBTYPE_POWERPC_970 100
45*f6dc9357SAndroid Build Coastguard Worker
46*f6dc9357SAndroid Build Coastguard Worker static const char * const k_PowerPc_SubTypes[] =
47*f6dc9357SAndroid Build Coastguard Worker {
48*f6dc9357SAndroid Build Coastguard Worker NULL
49*f6dc9357SAndroid Build Coastguard Worker , "601"
50*f6dc9357SAndroid Build Coastguard Worker , "602"
51*f6dc9357SAndroid Build Coastguard Worker , "603"
52*f6dc9357SAndroid Build Coastguard Worker , "603e"
53*f6dc9357SAndroid Build Coastguard Worker , "603ev"
54*f6dc9357SAndroid Build Coastguard Worker , "604"
55*f6dc9357SAndroid Build Coastguard Worker , "604e"
56*f6dc9357SAndroid Build Coastguard Worker , "620"
57*f6dc9357SAndroid Build Coastguard Worker , "750"
58*f6dc9357SAndroid Build Coastguard Worker , "7400"
59*f6dc9357SAndroid Build Coastguard Worker , "7450"
60*f6dc9357SAndroid Build Coastguard Worker };
61*f6dc9357SAndroid Build Coastguard Worker
62*f6dc9357SAndroid Build Coastguard Worker static const CUInt32PCharPair g_CpuPairs[] =
63*f6dc9357SAndroid Build Coastguard Worker {
64*f6dc9357SAndroid Build Coastguard Worker { CPU_TYPE_AMD64, "x64" },
65*f6dc9357SAndroid Build Coastguard Worker { CPU_TYPE_ARM64, "ARM64" },
66*f6dc9357SAndroid Build Coastguard Worker { CPU_TYPE_386, "x86" },
67*f6dc9357SAndroid Build Coastguard Worker { CPU_TYPE_ARM, "ARM" },
68*f6dc9357SAndroid Build Coastguard Worker { CPU_TYPE_SPARC, "SPARC" },
69*f6dc9357SAndroid Build Coastguard Worker { CPU_TYPE_PPC, "PowerPC" }
70*f6dc9357SAndroid Build Coastguard Worker };
71*f6dc9357SAndroid Build Coastguard Worker
72*f6dc9357SAndroid Build Coastguard Worker
73*f6dc9357SAndroid Build Coastguard Worker #define CMD_SEGMENT_32 1
74*f6dc9357SAndroid Build Coastguard Worker #define CMD_SEGMENT_64 0x19
75*f6dc9357SAndroid Build Coastguard Worker
76*f6dc9357SAndroid Build Coastguard Worker #define SECT_TYPE_MASK 0x000000FF
77*f6dc9357SAndroid Build Coastguard Worker #define SECT_ATTR_MASK 0xFFFFFF00
78*f6dc9357SAndroid Build Coastguard Worker
79*f6dc9357SAndroid Build Coastguard Worker #define SECT_ATTR_ZEROFILL 1
80*f6dc9357SAndroid Build Coastguard Worker
81*f6dc9357SAndroid Build Coastguard Worker static const char * const g_SectTypes[] =
82*f6dc9357SAndroid Build Coastguard Worker {
83*f6dc9357SAndroid Build Coastguard Worker "REGULAR"
84*f6dc9357SAndroid Build Coastguard Worker , "ZEROFILL"
85*f6dc9357SAndroid Build Coastguard Worker , "CSTRINGS"
86*f6dc9357SAndroid Build Coastguard Worker , "4BYTE_LITERALS"
87*f6dc9357SAndroid Build Coastguard Worker , "8BYTE_LITERALS"
88*f6dc9357SAndroid Build Coastguard Worker , "LITERAL_POINTERS"
89*f6dc9357SAndroid Build Coastguard Worker , "NON_LAZY_SYMBOL_POINTERS"
90*f6dc9357SAndroid Build Coastguard Worker , "LAZY_SYMBOL_POINTERS"
91*f6dc9357SAndroid Build Coastguard Worker , "SYMBOL_STUBS"
92*f6dc9357SAndroid Build Coastguard Worker , "MOD_INIT_FUNC_POINTERS"
93*f6dc9357SAndroid Build Coastguard Worker , "MOD_TERM_FUNC_POINTERS"
94*f6dc9357SAndroid Build Coastguard Worker , "COALESCED"
95*f6dc9357SAndroid Build Coastguard Worker , "GB_ZEROFILL"
96*f6dc9357SAndroid Build Coastguard Worker , "INTERPOSING"
97*f6dc9357SAndroid Build Coastguard Worker , "16BYTE_LITERALS"
98*f6dc9357SAndroid Build Coastguard Worker , "DTRACE_DOF"
99*f6dc9357SAndroid Build Coastguard Worker , "LAZY_DYLIB_SYMBOL_POINTERS"
100*f6dc9357SAndroid Build Coastguard Worker , "THREAD_LOCAL_REGULAR"
101*f6dc9357SAndroid Build Coastguard Worker , "THREAD_LOCAL_ZEROFILL"
102*f6dc9357SAndroid Build Coastguard Worker , "THREAD_LOCAL_VARIABLES"
103*f6dc9357SAndroid Build Coastguard Worker , "THREAD_LOCAL_VARIABLE_POINTERS"
104*f6dc9357SAndroid Build Coastguard Worker , "THREAD_LOCAL_INIT_FUNCTION_POINTERS"
105*f6dc9357SAndroid Build Coastguard Worker };
106*f6dc9357SAndroid Build Coastguard Worker
107*f6dc9357SAndroid Build Coastguard Worker enum EFileType
108*f6dc9357SAndroid Build Coastguard Worker {
109*f6dc9357SAndroid Build Coastguard Worker kType_OBJECT = 1,
110*f6dc9357SAndroid Build Coastguard Worker kType_EXECUTE,
111*f6dc9357SAndroid Build Coastguard Worker kType_FVMLIB,
112*f6dc9357SAndroid Build Coastguard Worker kType_CORE,
113*f6dc9357SAndroid Build Coastguard Worker kType_PRELOAD,
114*f6dc9357SAndroid Build Coastguard Worker kType_DYLIB,
115*f6dc9357SAndroid Build Coastguard Worker kType_DYLINKER,
116*f6dc9357SAndroid Build Coastguard Worker kType_BUNDLE,
117*f6dc9357SAndroid Build Coastguard Worker kType_DYLIB_STUB,
118*f6dc9357SAndroid Build Coastguard Worker kType_DSYM
119*f6dc9357SAndroid Build Coastguard Worker };
120*f6dc9357SAndroid Build Coastguard Worker
121*f6dc9357SAndroid Build Coastguard Worker static const char * const g_FileTypes[] =
122*f6dc9357SAndroid Build Coastguard Worker {
123*f6dc9357SAndroid Build Coastguard Worker "0"
124*f6dc9357SAndroid Build Coastguard Worker , "OBJECT"
125*f6dc9357SAndroid Build Coastguard Worker , "EXECUTE"
126*f6dc9357SAndroid Build Coastguard Worker , "FVMLIB"
127*f6dc9357SAndroid Build Coastguard Worker , "CORE"
128*f6dc9357SAndroid Build Coastguard Worker , "PRELOAD"
129*f6dc9357SAndroid Build Coastguard Worker , "DYLIB"
130*f6dc9357SAndroid Build Coastguard Worker , "DYLINKER"
131*f6dc9357SAndroid Build Coastguard Worker , "BUNDLE"
132*f6dc9357SAndroid Build Coastguard Worker , "DYLIB_STUB"
133*f6dc9357SAndroid Build Coastguard Worker , "DSYM"
134*f6dc9357SAndroid Build Coastguard Worker };
135*f6dc9357SAndroid Build Coastguard Worker
136*f6dc9357SAndroid Build Coastguard Worker
137*f6dc9357SAndroid Build Coastguard Worker static const char * const g_ArcFlags[] =
138*f6dc9357SAndroid Build Coastguard Worker {
139*f6dc9357SAndroid Build Coastguard Worker "NOUNDEFS"
140*f6dc9357SAndroid Build Coastguard Worker , "INCRLINK"
141*f6dc9357SAndroid Build Coastguard Worker , "DYLDLINK"
142*f6dc9357SAndroid Build Coastguard Worker , "BINDATLOAD"
143*f6dc9357SAndroid Build Coastguard Worker , "PREBOUND"
144*f6dc9357SAndroid Build Coastguard Worker , "SPLIT_SEGS"
145*f6dc9357SAndroid Build Coastguard Worker , "LAZY_INIT"
146*f6dc9357SAndroid Build Coastguard Worker , "TWOLEVEL"
147*f6dc9357SAndroid Build Coastguard Worker , "FORCE_FLAT"
148*f6dc9357SAndroid Build Coastguard Worker , "NOMULTIDEFS"
149*f6dc9357SAndroid Build Coastguard Worker , "NOFIXPREBINDING"
150*f6dc9357SAndroid Build Coastguard Worker , "PREBINDABLE"
151*f6dc9357SAndroid Build Coastguard Worker , "ALLMODSBOUND"
152*f6dc9357SAndroid Build Coastguard Worker , "SUBSECTIONS_VIA_SYMBOLS"
153*f6dc9357SAndroid Build Coastguard Worker , "CANONICAL"
154*f6dc9357SAndroid Build Coastguard Worker , "WEAK_DEFINES"
155*f6dc9357SAndroid Build Coastguard Worker , "BINDS_TO_WEAK"
156*f6dc9357SAndroid Build Coastguard Worker , "ALLOW_STACK_EXECUTION"
157*f6dc9357SAndroid Build Coastguard Worker , "ROOT_SAFE"
158*f6dc9357SAndroid Build Coastguard Worker , "SETUID_SAFE"
159*f6dc9357SAndroid Build Coastguard Worker , "NO_REEXPORTED_DYLIBS"
160*f6dc9357SAndroid Build Coastguard Worker , "PIE"
161*f6dc9357SAndroid Build Coastguard Worker , "DEAD_STRIPPABLE_DYLIB"
162*f6dc9357SAndroid Build Coastguard Worker , "HAS_TLV_DESCRIPTORS"
163*f6dc9357SAndroid Build Coastguard Worker , "NO_HEAP_EXECUTION"
164*f6dc9357SAndroid Build Coastguard Worker };
165*f6dc9357SAndroid Build Coastguard Worker
166*f6dc9357SAndroid Build Coastguard Worker
167*f6dc9357SAndroid Build Coastguard Worker static const CUInt32PCharPair g_SectFlags[] =
168*f6dc9357SAndroid Build Coastguard Worker {
169*f6dc9357SAndroid Build Coastguard Worker { 31, "PURE_INSTRUCTIONS" },
170*f6dc9357SAndroid Build Coastguard Worker { 30, "NO_TOC" },
171*f6dc9357SAndroid Build Coastguard Worker { 29, "STRIP_STATIC_SYMS" },
172*f6dc9357SAndroid Build Coastguard Worker { 28, "NO_DEAD_STRIP" },
173*f6dc9357SAndroid Build Coastguard Worker { 27, "LIVE_SUPPORT" },
174*f6dc9357SAndroid Build Coastguard Worker { 26, "SELF_MODIFYING_CODE" },
175*f6dc9357SAndroid Build Coastguard Worker { 25, "DEBUG" },
176*f6dc9357SAndroid Build Coastguard Worker { 10, "SOME_INSTRUCTIONS" },
177*f6dc9357SAndroid Build Coastguard Worker { 9, "EXT_RELOC" },
178*f6dc9357SAndroid Build Coastguard Worker { 8, "LOC_RELOC" }
179*f6dc9357SAndroid Build Coastguard Worker };
180*f6dc9357SAndroid Build Coastguard Worker
181*f6dc9357SAndroid Build Coastguard Worker
182*f6dc9357SAndroid Build Coastguard Worker // VM_PROT_*
183*f6dc9357SAndroid Build Coastguard Worker static const char * const g_SegmentProt[] =
184*f6dc9357SAndroid Build Coastguard Worker {
185*f6dc9357SAndroid Build Coastguard Worker "READ"
186*f6dc9357SAndroid Build Coastguard Worker , "WRITE"
187*f6dc9357SAndroid Build Coastguard Worker , "EXECUTE"
188*f6dc9357SAndroid Build Coastguard Worker /*
189*f6dc9357SAndroid Build Coastguard Worker , "NO_CHANGE"
190*f6dc9357SAndroid Build Coastguard Worker , "COPY"
191*f6dc9357SAndroid Build Coastguard Worker , "TRUSTED"
192*f6dc9357SAndroid Build Coastguard Worker , "IS_MASK"
193*f6dc9357SAndroid Build Coastguard Worker */
194*f6dc9357SAndroid Build Coastguard Worker };
195*f6dc9357SAndroid Build Coastguard Worker
196*f6dc9357SAndroid Build Coastguard Worker // SG_*
197*f6dc9357SAndroid Build Coastguard Worker
198*f6dc9357SAndroid Build Coastguard Worker static const char * const g_SegmentFlags[] =
199*f6dc9357SAndroid Build Coastguard Worker {
200*f6dc9357SAndroid Build Coastguard Worker "SG_HIGHVM"
201*f6dc9357SAndroid Build Coastguard Worker , "SG_FVMLIB"
202*f6dc9357SAndroid Build Coastguard Worker , "SG_NORELOC"
203*f6dc9357SAndroid Build Coastguard Worker , "SG_PROTECTED_VERSION_1"
204*f6dc9357SAndroid Build Coastguard Worker , "SG_READ_ONLY"
205*f6dc9357SAndroid Build Coastguard Worker };
206*f6dc9357SAndroid Build Coastguard Worker
207*f6dc9357SAndroid Build Coastguard Worker static const unsigned kNameSize = 16;
208*f6dc9357SAndroid Build Coastguard Worker
209*f6dc9357SAndroid Build Coastguard Worker struct CSegment
210*f6dc9357SAndroid Build Coastguard Worker {
211*f6dc9357SAndroid Build Coastguard Worker char Name[kNameSize];
212*f6dc9357SAndroid Build Coastguard Worker UInt32 MaxProt;
213*f6dc9357SAndroid Build Coastguard Worker UInt32 InitProt;
214*f6dc9357SAndroid Build Coastguard Worker UInt32 Flags;
215*f6dc9357SAndroid Build Coastguard Worker };
216*f6dc9357SAndroid Build Coastguard Worker
217*f6dc9357SAndroid Build Coastguard Worker struct CSection
218*f6dc9357SAndroid Build Coastguard Worker {
219*f6dc9357SAndroid Build Coastguard Worker char Name[kNameSize];
220*f6dc9357SAndroid Build Coastguard Worker // char SegName[kNameSize];
221*f6dc9357SAndroid Build Coastguard Worker UInt64 Va;
222*f6dc9357SAndroid Build Coastguard Worker UInt64 Pa;
223*f6dc9357SAndroid Build Coastguard Worker UInt64 VSize;
224*f6dc9357SAndroid Build Coastguard Worker UInt64 PSize;
225*f6dc9357SAndroid Build Coastguard Worker
226*f6dc9357SAndroid Build Coastguard Worker UInt32 Align;
227*f6dc9357SAndroid Build Coastguard Worker UInt32 Flags;
228*f6dc9357SAndroid Build Coastguard Worker unsigned SegmentIndex;
229*f6dc9357SAndroid Build Coastguard Worker bool IsDummy;
230*f6dc9357SAndroid Build Coastguard Worker
CSectionNArchive::NMacho::CSection231*f6dc9357SAndroid Build Coastguard Worker CSection(): IsDummy(false) {}
232*f6dc9357SAndroid Build Coastguard Worker // UInt64 GetPackSize() const { return Flags == SECT_ATTR_ZEROFILL ? 0 : Size; }
GetPackSizeNArchive::NMacho::CSection233*f6dc9357SAndroid Build Coastguard Worker UInt64 GetPackSize() const { return PSize; }
234*f6dc9357SAndroid Build Coastguard Worker };
235*f6dc9357SAndroid Build Coastguard Worker
236*f6dc9357SAndroid Build Coastguard Worker
237*f6dc9357SAndroid Build Coastguard Worker Z7_CLASS_IMP_CHandler_IInArchive_1(
238*f6dc9357SAndroid Build Coastguard Worker IArchiveAllowTail
239*f6dc9357SAndroid Build Coastguard Worker )
240*f6dc9357SAndroid Build Coastguard Worker CMyComPtr<IInStream> _inStream;
241*f6dc9357SAndroid Build Coastguard Worker CObjectVector<CSegment> _segments;
242*f6dc9357SAndroid Build Coastguard Worker CObjectVector<CSection> _sections;
243*f6dc9357SAndroid Build Coastguard Worker bool _allowTail;
244*f6dc9357SAndroid Build Coastguard Worker bool _mode64;
245*f6dc9357SAndroid Build Coastguard Worker bool _be;
246*f6dc9357SAndroid Build Coastguard Worker UInt32 _cpuType;
247*f6dc9357SAndroid Build Coastguard Worker UInt32 _cpuSubType;
248*f6dc9357SAndroid Build Coastguard Worker UInt32 _type;
249*f6dc9357SAndroid Build Coastguard Worker UInt32 _flags;
250*f6dc9357SAndroid Build Coastguard Worker UInt32 _headersSize;
251*f6dc9357SAndroid Build Coastguard Worker UInt64 _totalSize;
252*f6dc9357SAndroid Build Coastguard Worker
253*f6dc9357SAndroid Build Coastguard Worker HRESULT Open2(ISequentialInStream *stream);
254*f6dc9357SAndroid Build Coastguard Worker public:
255*f6dc9357SAndroid Build Coastguard Worker CHandler(): _allowTail(false) {}
256*f6dc9357SAndroid Build Coastguard Worker };
257*f6dc9357SAndroid Build Coastguard Worker
258*f6dc9357SAndroid Build Coastguard Worker static const Byte kArcProps[] =
259*f6dc9357SAndroid Build Coastguard Worker {
260*f6dc9357SAndroid Build Coastguard Worker kpidCpu,
261*f6dc9357SAndroid Build Coastguard Worker kpidBit64,
262*f6dc9357SAndroid Build Coastguard Worker kpidBigEndian,
263*f6dc9357SAndroid Build Coastguard Worker kpidCharacts,
264*f6dc9357SAndroid Build Coastguard Worker kpidHeadersSize
265*f6dc9357SAndroid Build Coastguard Worker };
266*f6dc9357SAndroid Build Coastguard Worker
267*f6dc9357SAndroid Build Coastguard Worker static const Byte kProps[] =
268*f6dc9357SAndroid Build Coastguard Worker {
269*f6dc9357SAndroid Build Coastguard Worker kpidPath,
270*f6dc9357SAndroid Build Coastguard Worker kpidSize,
271*f6dc9357SAndroid Build Coastguard Worker kpidPackSize,
272*f6dc9357SAndroid Build Coastguard Worker kpidCharacts,
273*f6dc9357SAndroid Build Coastguard Worker kpidOffset,
274*f6dc9357SAndroid Build Coastguard Worker kpidVa,
275*f6dc9357SAndroid Build Coastguard Worker kpidClusterSize // Align
276*f6dc9357SAndroid Build Coastguard Worker };
277*f6dc9357SAndroid Build Coastguard Worker
278*f6dc9357SAndroid Build Coastguard Worker IMP_IInArchive_Props
279*f6dc9357SAndroid Build Coastguard Worker IMP_IInArchive_ArcProps
280*f6dc9357SAndroid Build Coastguard Worker
281*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))
282*f6dc9357SAndroid Build Coastguard Worker {
283*f6dc9357SAndroid Build Coastguard Worker COM_TRY_BEGIN
284*f6dc9357SAndroid Build Coastguard Worker CPropVariant prop;
285*f6dc9357SAndroid Build Coastguard Worker switch (propID)
286*f6dc9357SAndroid Build Coastguard Worker {
287*f6dc9357SAndroid Build Coastguard Worker case kpidShortComment:
288*f6dc9357SAndroid Build Coastguard Worker case kpidCpu:
289*f6dc9357SAndroid Build Coastguard Worker {
290*f6dc9357SAndroid Build Coastguard Worker AString s;
291*f6dc9357SAndroid Build Coastguard Worker const UInt32 cpu = _cpuType & ~(UInt32)CPU_ARCH_ABI64;
292*f6dc9357SAndroid Build Coastguard Worker UInt32 flag64 = _cpuType & (UInt32)CPU_ARCH_ABI64;
293*f6dc9357SAndroid Build Coastguard Worker {
294*f6dc9357SAndroid Build Coastguard Worker s.Add_UInt32(cpu);
295*f6dc9357SAndroid Build Coastguard Worker for (unsigned i = 0; i < Z7_ARRAY_SIZE(g_CpuPairs); i++)
296*f6dc9357SAndroid Build Coastguard Worker {
297*f6dc9357SAndroid Build Coastguard Worker const CUInt32PCharPair &pair = g_CpuPairs[i];
298*f6dc9357SAndroid Build Coastguard Worker if (pair.Value == cpu || pair.Value == _cpuType)
299*f6dc9357SAndroid Build Coastguard Worker {
300*f6dc9357SAndroid Build Coastguard Worker if (pair.Value == _cpuType)
301*f6dc9357SAndroid Build Coastguard Worker flag64 = 0;
302*f6dc9357SAndroid Build Coastguard Worker s = pair.Name;
303*f6dc9357SAndroid Build Coastguard Worker break;
304*f6dc9357SAndroid Build Coastguard Worker }
305*f6dc9357SAndroid Build Coastguard Worker }
306*f6dc9357SAndroid Build Coastguard Worker
307*f6dc9357SAndroid Build Coastguard Worker if (flag64 != 0)
308*f6dc9357SAndroid Build Coastguard Worker s.Add_OptSpaced("64-bit");
309*f6dc9357SAndroid Build Coastguard Worker else if ((_cpuSubType & CPU_SUBTYPE_LIB64) && _cpuType != CPU_TYPE_AMD64)
310*f6dc9357SAndroid Build Coastguard Worker s.Add_OptSpaced("64-bit-lib");
311*f6dc9357SAndroid Build Coastguard Worker }
312*f6dc9357SAndroid Build Coastguard Worker const UInt32 t = _cpuSubType & ~(UInt32)CPU_SUBTYPE_LIB64;
313*f6dc9357SAndroid Build Coastguard Worker if (t != 0 && (t != CPU_SUBTYPE_I386_ALL || cpu != CPU_TYPE_386))
314*f6dc9357SAndroid Build Coastguard Worker {
315*f6dc9357SAndroid Build Coastguard Worker const char *n = NULL;
316*f6dc9357SAndroid Build Coastguard Worker if (cpu == CPU_TYPE_PPC)
317*f6dc9357SAndroid Build Coastguard Worker {
318*f6dc9357SAndroid Build Coastguard Worker if (t == CPU_SUBTYPE_POWERPC_970)
319*f6dc9357SAndroid Build Coastguard Worker n = "970";
320*f6dc9357SAndroid Build Coastguard Worker else if (t < Z7_ARRAY_SIZE(k_PowerPc_SubTypes))
321*f6dc9357SAndroid Build Coastguard Worker n = k_PowerPc_SubTypes[t];
322*f6dc9357SAndroid Build Coastguard Worker }
323*f6dc9357SAndroid Build Coastguard Worker s.Add_Space();
324*f6dc9357SAndroid Build Coastguard Worker if (n)
325*f6dc9357SAndroid Build Coastguard Worker s += n;
326*f6dc9357SAndroid Build Coastguard Worker else
327*f6dc9357SAndroid Build Coastguard Worker s.Add_UInt32(t);
328*f6dc9357SAndroid Build Coastguard Worker }
329*f6dc9357SAndroid Build Coastguard Worker prop = s;
330*f6dc9357SAndroid Build Coastguard Worker break;
331*f6dc9357SAndroid Build Coastguard Worker }
332*f6dc9357SAndroid Build Coastguard Worker case kpidCharacts:
333*f6dc9357SAndroid Build Coastguard Worker {
334*f6dc9357SAndroid Build Coastguard Worker // TYPE_TO_PROP(g_FileTypes, _type, prop); break;
335*f6dc9357SAndroid Build Coastguard Worker AString res (TypeToString(g_FileTypes, Z7_ARRAY_SIZE(g_FileTypes), _type));
336*f6dc9357SAndroid Build Coastguard Worker const AString s (FlagsToString(g_ArcFlags, Z7_ARRAY_SIZE(g_ArcFlags), _flags));
337*f6dc9357SAndroid Build Coastguard Worker if (!s.IsEmpty())
338*f6dc9357SAndroid Build Coastguard Worker {
339*f6dc9357SAndroid Build Coastguard Worker res.Add_Space();
340*f6dc9357SAndroid Build Coastguard Worker res += s;
341*f6dc9357SAndroid Build Coastguard Worker }
342*f6dc9357SAndroid Build Coastguard Worker prop = res;
343*f6dc9357SAndroid Build Coastguard Worker break;
344*f6dc9357SAndroid Build Coastguard Worker }
345*f6dc9357SAndroid Build Coastguard Worker case kpidPhySize: prop = _totalSize; break;
346*f6dc9357SAndroid Build Coastguard Worker case kpidHeadersSize: prop = _headersSize; break;
347*f6dc9357SAndroid Build Coastguard Worker case kpidBit64: if (_mode64) prop = _mode64; break;
348*f6dc9357SAndroid Build Coastguard Worker case kpidBigEndian: if (_be) prop = _be; break;
349*f6dc9357SAndroid Build Coastguard Worker case kpidExtension:
350*f6dc9357SAndroid Build Coastguard Worker {
351*f6dc9357SAndroid Build Coastguard Worker const char *ext = NULL;
352*f6dc9357SAndroid Build Coastguard Worker if (_type == kType_OBJECT)
353*f6dc9357SAndroid Build Coastguard Worker ext = "o";
354*f6dc9357SAndroid Build Coastguard Worker else if (_type == kType_BUNDLE)
355*f6dc9357SAndroid Build Coastguard Worker ext = "bundle";
356*f6dc9357SAndroid Build Coastguard Worker else if (_type == kType_DYLIB)
357*f6dc9357SAndroid Build Coastguard Worker ext = "dylib"; // main shared library usually does not have extension
358*f6dc9357SAndroid Build Coastguard Worker if (ext)
359*f6dc9357SAndroid Build Coastguard Worker prop = ext;
360*f6dc9357SAndroid Build Coastguard Worker break;
361*f6dc9357SAndroid Build Coastguard Worker }
362*f6dc9357SAndroid Build Coastguard Worker // case kpidIsSelfExe: prop = (_type == kType_EXECUTE); break;
363*f6dc9357SAndroid Build Coastguard Worker }
364*f6dc9357SAndroid Build Coastguard Worker prop.Detach(value);
365*f6dc9357SAndroid Build Coastguard Worker return S_OK;
366*f6dc9357SAndroid Build Coastguard Worker COM_TRY_END
367*f6dc9357SAndroid Build Coastguard Worker }
368*f6dc9357SAndroid Build Coastguard Worker
369*f6dc9357SAndroid Build Coastguard Worker static void AddName(AString &s, const char *name)
370*f6dc9357SAndroid Build Coastguard Worker {
371*f6dc9357SAndroid Build Coastguard Worker char temp[kNameSize + 1];
372*f6dc9357SAndroid Build Coastguard Worker memcpy(temp, name, kNameSize);
373*f6dc9357SAndroid Build Coastguard Worker temp[kNameSize] = 0;
374*f6dc9357SAndroid Build Coastguard Worker s += temp;
375*f6dc9357SAndroid Build Coastguard Worker }
376*f6dc9357SAndroid Build Coastguard Worker
377*f6dc9357SAndroid Build Coastguard Worker
378*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value))
379*f6dc9357SAndroid Build Coastguard Worker {
380*f6dc9357SAndroid Build Coastguard Worker COM_TRY_BEGIN
381*f6dc9357SAndroid Build Coastguard Worker CPropVariant prop;
382*f6dc9357SAndroid Build Coastguard Worker const CSection &item = _sections[index];
383*f6dc9357SAndroid Build Coastguard Worker switch (propID)
384*f6dc9357SAndroid Build Coastguard Worker {
385*f6dc9357SAndroid Build Coastguard Worker case kpidPath:
386*f6dc9357SAndroid Build Coastguard Worker {
387*f6dc9357SAndroid Build Coastguard Worker AString s;
388*f6dc9357SAndroid Build Coastguard Worker AddName(s, _segments[item.SegmentIndex].Name);
389*f6dc9357SAndroid Build Coastguard Worker if (!item.IsDummy)
390*f6dc9357SAndroid Build Coastguard Worker {
391*f6dc9357SAndroid Build Coastguard Worker // CSection::SegName and CSegment::Name are same in real cases.
392*f6dc9357SAndroid Build Coastguard Worker // AddName(s, item.SegName);
393*f6dc9357SAndroid Build Coastguard Worker AddName(s, item.Name);
394*f6dc9357SAndroid Build Coastguard Worker }
395*f6dc9357SAndroid Build Coastguard Worker prop = MultiByteToUnicodeString(s);
396*f6dc9357SAndroid Build Coastguard Worker break;
397*f6dc9357SAndroid Build Coastguard Worker }
398*f6dc9357SAndroid Build Coastguard Worker case kpidSize: /* prop = (UInt64)item.VSize; break; */
399*f6dc9357SAndroid Build Coastguard Worker case kpidPackSize: prop = (UInt64)item.GetPackSize(); break;
400*f6dc9357SAndroid Build Coastguard Worker case kpidCharacts:
401*f6dc9357SAndroid Build Coastguard Worker {
402*f6dc9357SAndroid Build Coastguard Worker AString res;
403*f6dc9357SAndroid Build Coastguard Worker {
404*f6dc9357SAndroid Build Coastguard Worker if (!item.IsDummy)
405*f6dc9357SAndroid Build Coastguard Worker {
406*f6dc9357SAndroid Build Coastguard Worker {
407*f6dc9357SAndroid Build Coastguard Worker const AString s (TypeToString(g_SectTypes, Z7_ARRAY_SIZE(g_SectTypes), item.Flags & SECT_TYPE_MASK));
408*f6dc9357SAndroid Build Coastguard Worker if (!s.IsEmpty())
409*f6dc9357SAndroid Build Coastguard Worker {
410*f6dc9357SAndroid Build Coastguard Worker res.Add_OptSpaced("sect_type:");
411*f6dc9357SAndroid Build Coastguard Worker res.Add_OptSpaced(s);
412*f6dc9357SAndroid Build Coastguard Worker }
413*f6dc9357SAndroid Build Coastguard Worker }
414*f6dc9357SAndroid Build Coastguard Worker {
415*f6dc9357SAndroid Build Coastguard Worker const AString s (FlagsToString(g_SectFlags, Z7_ARRAY_SIZE(g_SectFlags), item.Flags & SECT_ATTR_MASK));
416*f6dc9357SAndroid Build Coastguard Worker if (!s.IsEmpty())
417*f6dc9357SAndroid Build Coastguard Worker {
418*f6dc9357SAndroid Build Coastguard Worker res.Add_OptSpaced("sect_flags:");
419*f6dc9357SAndroid Build Coastguard Worker res.Add_OptSpaced(s);
420*f6dc9357SAndroid Build Coastguard Worker }
421*f6dc9357SAndroid Build Coastguard Worker }
422*f6dc9357SAndroid Build Coastguard Worker }
423*f6dc9357SAndroid Build Coastguard Worker const CSegment &seg = _segments[item.SegmentIndex];
424*f6dc9357SAndroid Build Coastguard Worker {
425*f6dc9357SAndroid Build Coastguard Worker const AString s (FlagsToString(g_SegmentFlags, Z7_ARRAY_SIZE(g_SegmentFlags), seg.Flags));
426*f6dc9357SAndroid Build Coastguard Worker if (!s.IsEmpty())
427*f6dc9357SAndroid Build Coastguard Worker {
428*f6dc9357SAndroid Build Coastguard Worker res.Add_OptSpaced("seg_flags:");
429*f6dc9357SAndroid Build Coastguard Worker res.Add_OptSpaced(s);
430*f6dc9357SAndroid Build Coastguard Worker }
431*f6dc9357SAndroid Build Coastguard Worker }
432*f6dc9357SAndroid Build Coastguard Worker {
433*f6dc9357SAndroid Build Coastguard Worker const AString s (FlagsToString(g_SegmentProt, Z7_ARRAY_SIZE(g_SegmentProt), seg.MaxProt));
434*f6dc9357SAndroid Build Coastguard Worker if (!s.IsEmpty())
435*f6dc9357SAndroid Build Coastguard Worker {
436*f6dc9357SAndroid Build Coastguard Worker res.Add_OptSpaced("max_prot:");
437*f6dc9357SAndroid Build Coastguard Worker res.Add_OptSpaced(s);
438*f6dc9357SAndroid Build Coastguard Worker }
439*f6dc9357SAndroid Build Coastguard Worker }
440*f6dc9357SAndroid Build Coastguard Worker {
441*f6dc9357SAndroid Build Coastguard Worker const AString s (FlagsToString(g_SegmentProt, Z7_ARRAY_SIZE(g_SegmentProt), seg.InitProt));
442*f6dc9357SAndroid Build Coastguard Worker if (!s.IsEmpty())
443*f6dc9357SAndroid Build Coastguard Worker {
444*f6dc9357SAndroid Build Coastguard Worker res.Add_OptSpaced("init_prot:");
445*f6dc9357SAndroid Build Coastguard Worker res.Add_OptSpaced(s);
446*f6dc9357SAndroid Build Coastguard Worker }
447*f6dc9357SAndroid Build Coastguard Worker }
448*f6dc9357SAndroid Build Coastguard Worker }
449*f6dc9357SAndroid Build Coastguard Worker if (!res.IsEmpty())
450*f6dc9357SAndroid Build Coastguard Worker prop = res;
451*f6dc9357SAndroid Build Coastguard Worker break;
452*f6dc9357SAndroid Build Coastguard Worker }
453*f6dc9357SAndroid Build Coastguard Worker case kpidOffset: prop = item.Pa; break;
454*f6dc9357SAndroid Build Coastguard Worker case kpidVa: prop = item.Va; break;
455*f6dc9357SAndroid Build Coastguard Worker case kpidClusterSize: prop = (UInt32)1 << item.Align; break;
456*f6dc9357SAndroid Build Coastguard Worker }
457*f6dc9357SAndroid Build Coastguard Worker prop.Detach(value);
458*f6dc9357SAndroid Build Coastguard Worker return S_OK;
459*f6dc9357SAndroid Build Coastguard Worker COM_TRY_END
460*f6dc9357SAndroid Build Coastguard Worker }
461*f6dc9357SAndroid Build Coastguard Worker
462*f6dc9357SAndroid Build Coastguard Worker
463*f6dc9357SAndroid Build Coastguard Worker HRESULT CHandler::Open2(ISequentialInStream *stream)
464*f6dc9357SAndroid Build Coastguard Worker {
465*f6dc9357SAndroid Build Coastguard Worker const UInt32 kStartHeaderSize = 7 * 4;
466*f6dc9357SAndroid Build Coastguard Worker
467*f6dc9357SAndroid Build Coastguard Worker Byte header[kStartHeaderSize];
468*f6dc9357SAndroid Build Coastguard Worker RINOK(ReadStream_FALSE(stream, header, kStartHeaderSize))
469*f6dc9357SAndroid Build Coastguard Worker bool be, mode64;
470*f6dc9357SAndroid Build Coastguard Worker switch (GetUi32(header))
471*f6dc9357SAndroid Build Coastguard Worker {
472*f6dc9357SAndroid Build Coastguard Worker case 0xCEFAEDFE: be = true; mode64 = false; break;
473*f6dc9357SAndroid Build Coastguard Worker case 0xCFFAEDFE: be = true; mode64 = true; break;
474*f6dc9357SAndroid Build Coastguard Worker case 0xFEEDFACE: be = false; mode64 = false; break;
475*f6dc9357SAndroid Build Coastguard Worker case 0xFEEDFACF: be = false; mode64 = true; break;
476*f6dc9357SAndroid Build Coastguard Worker default: return S_FALSE;
477*f6dc9357SAndroid Build Coastguard Worker }
478*f6dc9357SAndroid Build Coastguard Worker
479*f6dc9357SAndroid Build Coastguard Worker _mode64 = mode64;
480*f6dc9357SAndroid Build Coastguard Worker _be = be;
481*f6dc9357SAndroid Build Coastguard Worker
482*f6dc9357SAndroid Build Coastguard Worker const UInt32 numCommands = Get32(header + 0x10, be);
483*f6dc9357SAndroid Build Coastguard Worker const UInt32 commandsSize = Get32(header + 0x14, be);
484*f6dc9357SAndroid Build Coastguard Worker
485*f6dc9357SAndroid Build Coastguard Worker if (numCommands == 0)
486*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
487*f6dc9357SAndroid Build Coastguard Worker
488*f6dc9357SAndroid Build Coastguard Worker if (commandsSize > (1 << 24) ||
489*f6dc9357SAndroid Build Coastguard Worker numCommands > (1 << 21) ||
490*f6dc9357SAndroid Build Coastguard Worker numCommands * 8 > commandsSize)
491*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
492*f6dc9357SAndroid Build Coastguard Worker
493*f6dc9357SAndroid Build Coastguard Worker _cpuType = Get32(header + 4, be);
494*f6dc9357SAndroid Build Coastguard Worker _cpuSubType = Get32(header + 8, be);
495*f6dc9357SAndroid Build Coastguard Worker _type = Get32(header + 0xC, be);
496*f6dc9357SAndroid Build Coastguard Worker _flags = Get32(header + 0x18, be);
497*f6dc9357SAndroid Build Coastguard Worker
498*f6dc9357SAndroid Build Coastguard Worker /*
499*f6dc9357SAndroid Build Coastguard Worker // Probably the sections are in first commands. So we can reduce the number of commands.
500*f6dc9357SAndroid Build Coastguard Worker bool reduceCommands = false;
501*f6dc9357SAndroid Build Coastguard Worker const UInt32 kNumReduceCommands = 16;
502*f6dc9357SAndroid Build Coastguard Worker if (numCommands > kNumReduceCommands)
503*f6dc9357SAndroid Build Coastguard Worker {
504*f6dc9357SAndroid Build Coastguard Worker reduceCommands = true;
505*f6dc9357SAndroid Build Coastguard Worker numCommands = kNumReduceCommands;
506*f6dc9357SAndroid Build Coastguard Worker }
507*f6dc9357SAndroid Build Coastguard Worker */
508*f6dc9357SAndroid Build Coastguard Worker
509*f6dc9357SAndroid Build Coastguard Worker UInt32 startHeaderSize = kStartHeaderSize;
510*f6dc9357SAndroid Build Coastguard Worker if (mode64)
511*f6dc9357SAndroid Build Coastguard Worker startHeaderSize += 4;
512*f6dc9357SAndroid Build Coastguard Worker _headersSize = startHeaderSize + commandsSize;
513*f6dc9357SAndroid Build Coastguard Worker _totalSize = _headersSize;
514*f6dc9357SAndroid Build Coastguard Worker CByteArr buffer(_headersSize);
515*f6dc9357SAndroid Build Coastguard Worker RINOK(ReadStream_FALSE(stream, buffer + kStartHeaderSize, _headersSize - kStartHeaderSize))
516*f6dc9357SAndroid Build Coastguard Worker const Byte *buf = buffer + startHeaderSize;
517*f6dc9357SAndroid Build Coastguard Worker size_t size = _headersSize - startHeaderSize;
518*f6dc9357SAndroid Build Coastguard Worker for (UInt32 cmdIndex = 0; cmdIndex < numCommands; cmdIndex++)
519*f6dc9357SAndroid Build Coastguard Worker {
520*f6dc9357SAndroid Build Coastguard Worker if (size < 8)
521*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
522*f6dc9357SAndroid Build Coastguard Worker UInt32 cmd = Get32(buf, be);
523*f6dc9357SAndroid Build Coastguard Worker UInt32 cmdSize = Get32(buf + 4, be);
524*f6dc9357SAndroid Build Coastguard Worker if (cmdSize < 8)
525*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
526*f6dc9357SAndroid Build Coastguard Worker if (size < cmdSize)
527*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
528*f6dc9357SAndroid Build Coastguard Worker if (cmd == CMD_SEGMENT_32 || cmd == CMD_SEGMENT_64)
529*f6dc9357SAndroid Build Coastguard Worker {
530*f6dc9357SAndroid Build Coastguard Worker UInt32 offs = (cmd == CMD_SEGMENT_64) ? 0x48 : 0x38;
531*f6dc9357SAndroid Build Coastguard Worker if (cmdSize < offs)
532*f6dc9357SAndroid Build Coastguard Worker break;
533*f6dc9357SAndroid Build Coastguard Worker
534*f6dc9357SAndroid Build Coastguard Worker UInt64 vmAddr, vmSize, phAddr, phSize;
535*f6dc9357SAndroid Build Coastguard Worker
536*f6dc9357SAndroid Build Coastguard Worker {
537*f6dc9357SAndroid Build Coastguard Worker if (cmd == CMD_SEGMENT_64)
538*f6dc9357SAndroid Build Coastguard Worker {
539*f6dc9357SAndroid Build Coastguard Worker vmAddr = Get64(buf + 0x18, be);
540*f6dc9357SAndroid Build Coastguard Worker vmSize = Get64(buf + 0x20, be);
541*f6dc9357SAndroid Build Coastguard Worker phAddr = Get64(buf + 0x28, be);
542*f6dc9357SAndroid Build Coastguard Worker phSize = Get64(buf + 0x30, be);
543*f6dc9357SAndroid Build Coastguard Worker }
544*f6dc9357SAndroid Build Coastguard Worker else
545*f6dc9357SAndroid Build Coastguard Worker {
546*f6dc9357SAndroid Build Coastguard Worker vmAddr = Get32(buf + 0x18, be);
547*f6dc9357SAndroid Build Coastguard Worker vmSize = Get32(buf + 0x1C, be);
548*f6dc9357SAndroid Build Coastguard Worker phAddr = Get32(buf + 0x20, be);
549*f6dc9357SAndroid Build Coastguard Worker phSize = Get32(buf + 0x24, be);
550*f6dc9357SAndroid Build Coastguard Worker }
551*f6dc9357SAndroid Build Coastguard Worker {
552*f6dc9357SAndroid Build Coastguard Worker UInt64 totalSize = phAddr + phSize;
553*f6dc9357SAndroid Build Coastguard Worker if (totalSize < phAddr)
554*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
555*f6dc9357SAndroid Build Coastguard Worker if (_totalSize < totalSize)
556*f6dc9357SAndroid Build Coastguard Worker _totalSize = totalSize;
557*f6dc9357SAndroid Build Coastguard Worker }
558*f6dc9357SAndroid Build Coastguard Worker }
559*f6dc9357SAndroid Build Coastguard Worker
560*f6dc9357SAndroid Build Coastguard Worker CSegment seg;
561*f6dc9357SAndroid Build Coastguard Worker seg.MaxProt = Get32(buf + offs - 16, be);
562*f6dc9357SAndroid Build Coastguard Worker seg.InitProt = Get32(buf + offs - 12, be);
563*f6dc9357SAndroid Build Coastguard Worker seg.Flags = Get32(buf + offs - 4, be);
564*f6dc9357SAndroid Build Coastguard Worker memcpy(seg.Name, buf + 8, kNameSize);
565*f6dc9357SAndroid Build Coastguard Worker _segments.Add(seg);
566*f6dc9357SAndroid Build Coastguard Worker
567*f6dc9357SAndroid Build Coastguard Worker UInt32 numSections = Get32(buf + offs - 8, be);
568*f6dc9357SAndroid Build Coastguard Worker if (numSections > (1 << 8))
569*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
570*f6dc9357SAndroid Build Coastguard Worker
571*f6dc9357SAndroid Build Coastguard Worker if (numSections == 0)
572*f6dc9357SAndroid Build Coastguard Worker {
573*f6dc9357SAndroid Build Coastguard Worker CSection § = _sections.AddNew();
574*f6dc9357SAndroid Build Coastguard Worker sect.IsDummy = true;
575*f6dc9357SAndroid Build Coastguard Worker sect.SegmentIndex = _segments.Size() - 1;
576*f6dc9357SAndroid Build Coastguard Worker sect.Va = vmAddr;
577*f6dc9357SAndroid Build Coastguard Worker sect.PSize = phSize;
578*f6dc9357SAndroid Build Coastguard Worker sect.VSize = vmSize;
579*f6dc9357SAndroid Build Coastguard Worker sect.Pa = phAddr;
580*f6dc9357SAndroid Build Coastguard Worker sect.Align = 0;
581*f6dc9357SAndroid Build Coastguard Worker sect.Flags = 0;
582*f6dc9357SAndroid Build Coastguard Worker }
583*f6dc9357SAndroid Build Coastguard Worker else do
584*f6dc9357SAndroid Build Coastguard Worker {
585*f6dc9357SAndroid Build Coastguard Worker const UInt32 headSize = (cmd == CMD_SEGMENT_64) ? 0x50 : 0x44;
586*f6dc9357SAndroid Build Coastguard Worker const Byte *p = buf + offs;
587*f6dc9357SAndroid Build Coastguard Worker if (cmdSize - offs < headSize)
588*f6dc9357SAndroid Build Coastguard Worker break;
589*f6dc9357SAndroid Build Coastguard Worker CSection § = _sections.AddNew();
590*f6dc9357SAndroid Build Coastguard Worker unsigned f32Offset;
591*f6dc9357SAndroid Build Coastguard Worker if (cmd == CMD_SEGMENT_64)
592*f6dc9357SAndroid Build Coastguard Worker {
593*f6dc9357SAndroid Build Coastguard Worker sect.Va = Get64(p + 0x20, be);
594*f6dc9357SAndroid Build Coastguard Worker sect.VSize = Get64(p + 0x28, be);
595*f6dc9357SAndroid Build Coastguard Worker f32Offset = 0x30;
596*f6dc9357SAndroid Build Coastguard Worker }
597*f6dc9357SAndroid Build Coastguard Worker else
598*f6dc9357SAndroid Build Coastguard Worker {
599*f6dc9357SAndroid Build Coastguard Worker sect.Va = Get32(p + 0x20, be);
600*f6dc9357SAndroid Build Coastguard Worker sect.VSize = Get32(p + 0x24, be);
601*f6dc9357SAndroid Build Coastguard Worker f32Offset = 0x28;
602*f6dc9357SAndroid Build Coastguard Worker }
603*f6dc9357SAndroid Build Coastguard Worker sect.Pa = Get32(p + f32Offset, be);
604*f6dc9357SAndroid Build Coastguard Worker sect.Align = Get32(p + f32Offset + 4, be);
605*f6dc9357SAndroid Build Coastguard Worker // sect.reloff = Get32(p + f32Offset + 8, be);
606*f6dc9357SAndroid Build Coastguard Worker // sect.nreloc = Get32(p + f32Offset + 12, be);
607*f6dc9357SAndroid Build Coastguard Worker sect.Flags = Get32(p + f32Offset + 16, be);
608*f6dc9357SAndroid Build Coastguard Worker if ((sect.Flags & SECT_TYPE_MASK) == SECT_ATTR_ZEROFILL)
609*f6dc9357SAndroid Build Coastguard Worker sect.PSize = 0;
610*f6dc9357SAndroid Build Coastguard Worker else
611*f6dc9357SAndroid Build Coastguard Worker sect.PSize = sect.VSize;
612*f6dc9357SAndroid Build Coastguard Worker memcpy(sect.Name, p, kNameSize);
613*f6dc9357SAndroid Build Coastguard Worker // memcpy(sect.SegName, p + kNameSize, kNameSize);
614*f6dc9357SAndroid Build Coastguard Worker sect.SegmentIndex = _segments.Size() - 1;
615*f6dc9357SAndroid Build Coastguard Worker offs += headSize;
616*f6dc9357SAndroid Build Coastguard Worker }
617*f6dc9357SAndroid Build Coastguard Worker while (--numSections);
618*f6dc9357SAndroid Build Coastguard Worker
619*f6dc9357SAndroid Build Coastguard Worker if (offs != cmdSize)
620*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
621*f6dc9357SAndroid Build Coastguard Worker }
622*f6dc9357SAndroid Build Coastguard Worker buf += cmdSize;
623*f6dc9357SAndroid Build Coastguard Worker size -= cmdSize;
624*f6dc9357SAndroid Build Coastguard Worker }
625*f6dc9357SAndroid Build Coastguard Worker // return (reduceCommands || (size == 0)) ? S_OK : S_FALSE;
626*f6dc9357SAndroid Build Coastguard Worker if (size != 0)
627*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
628*f6dc9357SAndroid Build Coastguard Worker
629*f6dc9357SAndroid Build Coastguard Worker return S_OK;
630*f6dc9357SAndroid Build Coastguard Worker }
631*f6dc9357SAndroid Build Coastguard Worker
632*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::Open(IInStream *inStream,
633*f6dc9357SAndroid Build Coastguard Worker const UInt64 * /* maxCheckStartPosition */,
634*f6dc9357SAndroid Build Coastguard Worker IArchiveOpenCallback * /* openArchiveCallback */))
635*f6dc9357SAndroid Build Coastguard Worker {
636*f6dc9357SAndroid Build Coastguard Worker COM_TRY_BEGIN
637*f6dc9357SAndroid Build Coastguard Worker Close();
638*f6dc9357SAndroid Build Coastguard Worker RINOK(Open2(inStream))
639*f6dc9357SAndroid Build Coastguard Worker if (!_allowTail)
640*f6dc9357SAndroid Build Coastguard Worker {
641*f6dc9357SAndroid Build Coastguard Worker UInt64 fileSize;
642*f6dc9357SAndroid Build Coastguard Worker RINOK(InStream_GetSize_SeekToEnd(inStream, fileSize))
643*f6dc9357SAndroid Build Coastguard Worker if (fileSize > _totalSize)
644*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
645*f6dc9357SAndroid Build Coastguard Worker }
646*f6dc9357SAndroid Build Coastguard Worker _inStream = inStream;
647*f6dc9357SAndroid Build Coastguard Worker return S_OK;
648*f6dc9357SAndroid Build Coastguard Worker COM_TRY_END
649*f6dc9357SAndroid Build Coastguard Worker }
650*f6dc9357SAndroid Build Coastguard Worker
651*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::Close())
652*f6dc9357SAndroid Build Coastguard Worker {
653*f6dc9357SAndroid Build Coastguard Worker _totalSize = 0;
654*f6dc9357SAndroid Build Coastguard Worker _inStream.Release();
655*f6dc9357SAndroid Build Coastguard Worker _sections.Clear();
656*f6dc9357SAndroid Build Coastguard Worker _segments.Clear();
657*f6dc9357SAndroid Build Coastguard Worker return S_OK;
658*f6dc9357SAndroid Build Coastguard Worker }
659*f6dc9357SAndroid Build Coastguard Worker
660*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::GetNumberOfItems(UInt32 *numItems))
661*f6dc9357SAndroid Build Coastguard Worker {
662*f6dc9357SAndroid Build Coastguard Worker *numItems = _sections.Size();
663*f6dc9357SAndroid Build Coastguard Worker return S_OK;
664*f6dc9357SAndroid Build Coastguard Worker }
665*f6dc9357SAndroid Build Coastguard Worker
666*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
667*f6dc9357SAndroid Build Coastguard Worker Int32 testMode, IArchiveExtractCallback *extractCallback))
668*f6dc9357SAndroid Build Coastguard Worker {
669*f6dc9357SAndroid Build Coastguard Worker COM_TRY_BEGIN
670*f6dc9357SAndroid Build Coastguard Worker const bool allFilesMode = (numItems == (UInt32)(Int32)-1);
671*f6dc9357SAndroid Build Coastguard Worker if (allFilesMode)
672*f6dc9357SAndroid Build Coastguard Worker numItems = _sections.Size();
673*f6dc9357SAndroid Build Coastguard Worker if (numItems == 0)
674*f6dc9357SAndroid Build Coastguard Worker return S_OK;
675*f6dc9357SAndroid Build Coastguard Worker UInt64 totalSize = 0;
676*f6dc9357SAndroid Build Coastguard Worker UInt32 i;
677*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < numItems; i++)
678*f6dc9357SAndroid Build Coastguard Worker totalSize += _sections[allFilesMode ? i : indices[i]].GetPackSize();
679*f6dc9357SAndroid Build Coastguard Worker extractCallback->SetTotal(totalSize);
680*f6dc9357SAndroid Build Coastguard Worker
681*f6dc9357SAndroid Build Coastguard Worker UInt64 currentTotalSize = 0;
682*f6dc9357SAndroid Build Coastguard Worker UInt64 currentItemSize;
683*f6dc9357SAndroid Build Coastguard Worker
684*f6dc9357SAndroid Build Coastguard Worker NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder();
685*f6dc9357SAndroid Build Coastguard Worker CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec;
686*f6dc9357SAndroid Build Coastguard Worker
687*f6dc9357SAndroid Build Coastguard Worker CLocalProgress *lps = new CLocalProgress;
688*f6dc9357SAndroid Build Coastguard Worker CMyComPtr<ICompressProgressInfo> progress = lps;
689*f6dc9357SAndroid Build Coastguard Worker lps->Init(extractCallback, false);
690*f6dc9357SAndroid Build Coastguard Worker
691*f6dc9357SAndroid Build Coastguard Worker CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream;
692*f6dc9357SAndroid Build Coastguard Worker CMyComPtr<ISequentialInStream> inStream(streamSpec);
693*f6dc9357SAndroid Build Coastguard Worker streamSpec->SetStream(_inStream);
694*f6dc9357SAndroid Build Coastguard Worker
695*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < numItems; i++, currentTotalSize += currentItemSize)
696*f6dc9357SAndroid Build Coastguard Worker {
697*f6dc9357SAndroid Build Coastguard Worker lps->InSize = lps->OutSize = currentTotalSize;
698*f6dc9357SAndroid Build Coastguard Worker RINOK(lps->SetCur())
699*f6dc9357SAndroid Build Coastguard Worker const Int32 askMode = testMode ?
700*f6dc9357SAndroid Build Coastguard Worker NExtract::NAskMode::kTest :
701*f6dc9357SAndroid Build Coastguard Worker NExtract::NAskMode::kExtract;
702*f6dc9357SAndroid Build Coastguard Worker const UInt32 index = allFilesMode ? i : indices[i];
703*f6dc9357SAndroid Build Coastguard Worker const CSection &item = _sections[index];
704*f6dc9357SAndroid Build Coastguard Worker currentItemSize = item.GetPackSize();
705*f6dc9357SAndroid Build Coastguard Worker
706*f6dc9357SAndroid Build Coastguard Worker CMyComPtr<ISequentialOutStream> outStream;
707*f6dc9357SAndroid Build Coastguard Worker RINOK(extractCallback->GetStream(index, &outStream, askMode))
708*f6dc9357SAndroid Build Coastguard Worker if (!testMode && !outStream)
709*f6dc9357SAndroid Build Coastguard Worker continue;
710*f6dc9357SAndroid Build Coastguard Worker
711*f6dc9357SAndroid Build Coastguard Worker RINOK(extractCallback->PrepareOperation(askMode))
712*f6dc9357SAndroid Build Coastguard Worker RINOK(InStream_SeekSet(_inStream, item.Pa))
713*f6dc9357SAndroid Build Coastguard Worker streamSpec->Init(currentItemSize);
714*f6dc9357SAndroid Build Coastguard Worker RINOK(copyCoder->Code(inStream, outStream, NULL, NULL, progress))
715*f6dc9357SAndroid Build Coastguard Worker outStream.Release();
716*f6dc9357SAndroid Build Coastguard Worker RINOK(extractCallback->SetOperationResult(copyCoderSpec->TotalSize == currentItemSize ?
717*f6dc9357SAndroid Build Coastguard Worker NExtract::NOperationResult::kOK:
718*f6dc9357SAndroid Build Coastguard Worker NExtract::NOperationResult::kDataError))
719*f6dc9357SAndroid Build Coastguard Worker }
720*f6dc9357SAndroid Build Coastguard Worker return S_OK;
721*f6dc9357SAndroid Build Coastguard Worker COM_TRY_END
722*f6dc9357SAndroid Build Coastguard Worker }
723*f6dc9357SAndroid Build Coastguard Worker
724*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::AllowTail(Int32 allowTail))
725*f6dc9357SAndroid Build Coastguard Worker {
726*f6dc9357SAndroid Build Coastguard Worker _allowTail = IntToBool(allowTail);
727*f6dc9357SAndroid Build Coastguard Worker return S_OK;
728*f6dc9357SAndroid Build Coastguard Worker }
729*f6dc9357SAndroid Build Coastguard Worker
730*f6dc9357SAndroid Build Coastguard Worker static const Byte k_Signature[] = {
731*f6dc9357SAndroid Build Coastguard Worker 4, 0xCE, 0xFA, 0xED, 0xFE,
732*f6dc9357SAndroid Build Coastguard Worker 4, 0xCF, 0xFA, 0xED, 0xFE,
733*f6dc9357SAndroid Build Coastguard Worker 4, 0xFE, 0xED, 0xFA, 0xCE,
734*f6dc9357SAndroid Build Coastguard Worker 4, 0xFE, 0xED, 0xFA, 0xCF };
735*f6dc9357SAndroid Build Coastguard Worker
736*f6dc9357SAndroid Build Coastguard Worker REGISTER_ARC_I(
737*f6dc9357SAndroid Build Coastguard Worker "MachO", "macho", NULL, 0xDF,
738*f6dc9357SAndroid Build Coastguard Worker k_Signature,
739*f6dc9357SAndroid Build Coastguard Worker 0,
740*f6dc9357SAndroid Build Coastguard Worker NArcInfoFlags::kMultiSignature |
741*f6dc9357SAndroid Build Coastguard Worker NArcInfoFlags::kPreArc,
742*f6dc9357SAndroid Build Coastguard Worker NULL)
743*f6dc9357SAndroid Build Coastguard Worker
744*f6dc9357SAndroid Build Coastguard Worker }}
745