xref: /aosp_15_r20/external/lzma/CPP/7zip/Archive/MachoHandler.cpp (revision f6dc9357d832569d4d1f5d24eacdb3935a1ae8e6)
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 &sect = _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 &sect = _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