mirror of
https://github.com/Xevion/easy7zip.git
synced 2026-01-31 20:24:05 -06:00
9.34
This commit is contained in:
committed by
Kornel Lesiński
parent
83f8ddcc5b
commit
f08f4dcc3c
Executable → Regular
+408
-244
@@ -4,10 +4,12 @@
|
||||
|
||||
#include "../../../C/CpuArch.h"
|
||||
|
||||
#include "Common/Buffer.h"
|
||||
#include "Common/ComTry.h"
|
||||
#include "../../Common/ComTry.h"
|
||||
#include "../../Common/MyBuffer.h"
|
||||
#include "../../Common/StringConvert.h"
|
||||
#include "../../Common/IntToString.h"
|
||||
|
||||
#include "Windows/PropVariantUtils.h"
|
||||
#include "../../Windows/PropVariantUtils.h"
|
||||
|
||||
#include "../Common/LimitedStreams.h"
|
||||
#include "../Common/ProgressUtils.h"
|
||||
@@ -16,65 +18,142 @@
|
||||
|
||||
#include "../Compress/CopyCoder.h"
|
||||
|
||||
static UInt32 Get32(const Byte *p, int be) { if (be) return GetBe32(p); return GetUi32(p); }
|
||||
static UInt64 Get64(const Byte *p, int be) { if (be) return GetBe64(p); return GetUi64(p); }
|
||||
static UInt32 Get32(const Byte *p, bool be) { if (be) return GetBe32(p); return GetUi32(p); }
|
||||
static UInt64 Get64(const Byte *p, bool be) { if (be) return GetBe64(p); return GetUi64(p); }
|
||||
|
||||
using namespace NWindows;
|
||||
using namespace NCOM;
|
||||
|
||||
namespace NArchive {
|
||||
namespace NMacho {
|
||||
|
||||
#define MACH_ARCH_ABI64 (1 << 24)
|
||||
#define MACH_MACHINE_386 7
|
||||
#define MACH_MACHINE_ARM 12
|
||||
#define MACH_MACHINE_SPARC 14
|
||||
#define MACH_MACHINE_PPC 18
|
||||
#define CPU_ARCH_ABI64 (1 << 24)
|
||||
#define CPU_TYPE_386 7
|
||||
#define CPU_TYPE_ARM 12
|
||||
#define CPU_TYPE_SPARC 14
|
||||
#define CPU_TYPE_PPC 18
|
||||
|
||||
#define MACH_MACHINE_PPC64 (MACH_ARCH_ABI64 | MACH_MACHINE_PPC)
|
||||
#define MACH_MACHINE_AMD64 (MACH_ARCH_ABI64 | MACH_MACHINE_386)
|
||||
#define CPU_SUBTYPE_I386_ALL 3
|
||||
|
||||
#define MACH_CMD_SEGMENT_32 1
|
||||
#define MACH_CMD_SEGMENT_64 0x19
|
||||
#define CPU_TYPE_PPC64 (CPU_ARCH_ABI64 | CPU_TYPE_PPC)
|
||||
#define CPU_TYPE_AMD64 (CPU_ARCH_ABI64 | CPU_TYPE_386)
|
||||
|
||||
#define MACH_SECT_TYPE_MASK 0x000000FF
|
||||
#define MACH_SECT_ATTR_MASK 0xFFFFFF00
|
||||
#define CPU_SUBTYPE_LIB64 (1 << 31)
|
||||
|
||||
#define MACH_SECT_ATTR_ZEROFILL 1
|
||||
#define CPU_SUBTYPE_POWERPC_970 100
|
||||
|
||||
static const char *k_PowerPc_SubTypes[] =
|
||||
{
|
||||
NULL
|
||||
, "601"
|
||||
, "602"
|
||||
, "603"
|
||||
, "603e"
|
||||
, "603ev"
|
||||
, "604"
|
||||
, "604e"
|
||||
, "620"
|
||||
, "750"
|
||||
, "7400"
|
||||
, "7450"
|
||||
};
|
||||
|
||||
static const CUInt32PCharPair g_CpuPairs[] =
|
||||
{
|
||||
{ CPU_TYPE_386, "x86" },
|
||||
{ CPU_TYPE_ARM, "ARM" },
|
||||
{ CPU_TYPE_SPARC, "SPARC" },
|
||||
{ CPU_TYPE_PPC, "PowerPC" }
|
||||
};
|
||||
|
||||
|
||||
#define CMD_SEGMENT_32 1
|
||||
#define CMD_SEGMENT_64 0x19
|
||||
|
||||
#define SECT_TYPE_MASK 0x000000FF
|
||||
#define SECT_ATTR_MASK 0xFFFFFF00
|
||||
|
||||
#define SECT_ATTR_ZEROFILL 1
|
||||
|
||||
static const char *g_SectTypes[] =
|
||||
{
|
||||
"REGULAR",
|
||||
"ZEROFILL",
|
||||
"CSTRINGS",
|
||||
"4BYTE_LITERALS",
|
||||
"8BYTE_LITERALS",
|
||||
"LITERAL_POINTERS",
|
||||
"NON_LAZY_SYMBOL_POINTERS",
|
||||
"LAZY_SYMBOL_POINTERS",
|
||||
"SYMBOL_STUBS",
|
||||
"MOD_INIT_FUNC_POINTERS",
|
||||
"MOD_TERM_FUNC_POINTERS",
|
||||
"COALESCED",
|
||||
"GB_ZEROFILL",
|
||||
"INTERPOSING",
|
||||
"16BYTE_LITERALS"
|
||||
"REGULAR"
|
||||
, "ZEROFILL"
|
||||
, "CSTRINGS"
|
||||
, "4BYTE_LITERALS"
|
||||
, "8BYTE_LITERALS"
|
||||
, "LITERAL_POINTERS"
|
||||
, "NON_LAZY_SYMBOL_POINTERS"
|
||||
, "LAZY_SYMBOL_POINTERS"
|
||||
, "SYMBOL_STUBS"
|
||||
, "MOD_INIT_FUNC_POINTERS"
|
||||
, "MOD_TERM_FUNC_POINTERS"
|
||||
, "COALESCED"
|
||||
, "GB_ZEROFILL"
|
||||
, "INTERPOSING"
|
||||
, "16BYTE_LITERALS"
|
||||
};
|
||||
|
||||
enum EFileType
|
||||
{
|
||||
kType_OBJECT = 1,
|
||||
kType_EXECUTE,
|
||||
kType_FVMLIB,
|
||||
kType_CORE,
|
||||
kType_PRELOAD,
|
||||
kType_DYLIB,
|
||||
kType_DYLINKER,
|
||||
kType_BUNDLE,
|
||||
kType_DYLIB_STUB,
|
||||
kType_DSYM
|
||||
};
|
||||
|
||||
static const char *g_FileTypes[] =
|
||||
{
|
||||
"0",
|
||||
"OBJECT",
|
||||
"EXECUTE",
|
||||
"FVMLIB",
|
||||
"CORE",
|
||||
"PRELOAD",
|
||||
"DYLIB",
|
||||
"DYLINKER",
|
||||
"BUNDLE",
|
||||
"DYLIB_STUB",
|
||||
"DSYM"
|
||||
"0"
|
||||
, "OBJECT"
|
||||
, "EXECUTE"
|
||||
, "FVMLIB"
|
||||
, "CORE"
|
||||
, "PRELOAD"
|
||||
, "DYLIB"
|
||||
, "DYLINKER"
|
||||
, "BUNDLE"
|
||||
, "DYLIB_STUB"
|
||||
, "DSYM"
|
||||
};
|
||||
|
||||
|
||||
static const char *g_ArcFlags[] =
|
||||
{
|
||||
"NOUNDEFS"
|
||||
, "INCRLINK"
|
||||
, "DYLDLINK"
|
||||
, "BINDATLOAD"
|
||||
, "PREBOUND"
|
||||
, "SPLIT_SEGS"
|
||||
, "LAZY_INIT"
|
||||
, "TWOLEVEL"
|
||||
, "FORCE_FLAT"
|
||||
, "NOMULTIDEFS"
|
||||
, "NOFIXPREBINDING"
|
||||
, "PREBINDABLE"
|
||||
, "ALLMODSBOUND"
|
||||
, "SUBSECTIONS_VIA_SYMBOLS"
|
||||
, "CANONICAL"
|
||||
, "WEAK_DEFINES"
|
||||
, "BINDS_TO_WEAK"
|
||||
, "ALLOW_STACK_EXECUTION"
|
||||
, "ROOT_SAFE"
|
||||
, "SETUID_SAFE"
|
||||
, "NO_REEXPORTED_DYLIBS"
|
||||
, "PIE"
|
||||
, "DEAD_STRIPPABLE_DYLIB"
|
||||
, "HAS_TLV_DESCRIPTORS"
|
||||
, "NO_HEAP_EXECUTION"
|
||||
};
|
||||
|
||||
|
||||
static const CUInt32PCharPair g_Flags[] =
|
||||
{
|
||||
{ 31, "PURE_INSTRUCTIONS" },
|
||||
@@ -89,16 +168,6 @@ static const CUInt32PCharPair g_Flags[] =
|
||||
{ 8, "LOC_RELOC" }
|
||||
};
|
||||
|
||||
static const CUInt32PCharPair g_MachinePairs[] =
|
||||
{
|
||||
{ MACH_MACHINE_386, "x86" },
|
||||
{ MACH_MACHINE_ARM, "ARM" },
|
||||
{ MACH_MACHINE_SPARC, "SPARC" },
|
||||
{ MACH_MACHINE_PPC, "PowerPC" },
|
||||
{ MACH_MACHINE_PPC64, "PowerPC 64-bit" },
|
||||
{ MACH_MACHINE_AMD64, "x64" }
|
||||
};
|
||||
|
||||
static const int kNameSize = 16;
|
||||
|
||||
struct CSegment
|
||||
@@ -121,192 +190,54 @@ struct CSection
|
||||
bool IsDummy;
|
||||
|
||||
CSection(): IsDummy(false) {}
|
||||
// UInt64 GetPackSize() const { return Flags == MACH_SECT_ATTR_ZEROFILL ? 0 : Size; }
|
||||
// UInt64 GetPackSize() const { return Flags == SECT_ATTR_ZEROFILL ? 0 : Size; }
|
||||
UInt64 GetPackSize() const { return PSize; }
|
||||
};
|
||||
|
||||
|
||||
class CHandler:
|
||||
public IInArchive,
|
||||
public IArchiveAllowTail,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
CMyComPtr<IInStream> _inStream;
|
||||
CObjectVector<CSegment> _segments;
|
||||
CObjectVector<CSection> _sections;
|
||||
bool _allowTail;
|
||||
bool _mode64;
|
||||
bool _be;
|
||||
UInt32 _machine;
|
||||
UInt32 _cpuType;
|
||||
UInt32 _cpuSubType;
|
||||
UInt32 _type;
|
||||
UInt32 _flags;
|
||||
UInt32 _headersSize;
|
||||
UInt64 _totalSize;
|
||||
|
||||
HRESULT Open2(ISequentialInStream *stream);
|
||||
bool Parse(const Byte *buf, UInt32 size);
|
||||
public:
|
||||
MY_UNKNOWN_IMP1(IInArchive)
|
||||
MY_UNKNOWN_IMP2(IInArchive, IArchiveAllowTail)
|
||||
INTERFACE_IInArchive(;)
|
||||
STDMETHOD(AllowTail)(Int32 allowTail);
|
||||
CHandler(): _allowTail(false) {}
|
||||
};
|
||||
|
||||
bool CHandler::Parse(const Byte *buf, UInt32 size)
|
||||
static const Byte kArcProps[] =
|
||||
{
|
||||
bool mode64 = _mode64;
|
||||
bool be = _be;
|
||||
|
||||
const Byte *bufStart = buf;
|
||||
bool reduceCommands = false;
|
||||
if (size < 512)
|
||||
return false;
|
||||
|
||||
_machine = Get32(buf + 4, be);
|
||||
_type = Get32(buf + 0xC, be);
|
||||
|
||||
UInt32 numCommands = Get32(buf + 0x10, be);
|
||||
UInt32 commandsSize = Get32(buf + 0x14, be);
|
||||
if (commandsSize > size)
|
||||
return false;
|
||||
|
||||
if (commandsSize > (1 << 24) || numCommands > (1 << 18))
|
||||
return false;
|
||||
|
||||
if (numCommands > 16)
|
||||
{
|
||||
reduceCommands = true;
|
||||
numCommands = 16;
|
||||
}
|
||||
|
||||
_headersSize = 0;
|
||||
|
||||
buf += 0x1C;
|
||||
size -= 0x1C;
|
||||
|
||||
if (mode64)
|
||||
{
|
||||
buf += 4;
|
||||
size -= 4;
|
||||
}
|
||||
|
||||
_totalSize = (UInt32)(buf - bufStart);
|
||||
if (commandsSize < size)
|
||||
size = commandsSize;
|
||||
|
||||
for (UInt32 cmdIndex = 0; cmdIndex < numCommands; cmdIndex++)
|
||||
{
|
||||
if (size < 8)
|
||||
return false;
|
||||
UInt32 cmd = Get32(buf, be);
|
||||
UInt32 cmdSize = Get32(buf + 4, be);
|
||||
if (size < cmdSize)
|
||||
return false;
|
||||
if (cmd == MACH_CMD_SEGMENT_32 || cmd == MACH_CMD_SEGMENT_64)
|
||||
{
|
||||
UInt32 offs = (cmd == MACH_CMD_SEGMENT_64) ? 0x48 : 0x38;
|
||||
if (cmdSize < offs)
|
||||
break;
|
||||
|
||||
UInt64 vmAddr, vmSize, phAddr, phSize;
|
||||
|
||||
{
|
||||
if (cmd == MACH_CMD_SEGMENT_64)
|
||||
{
|
||||
vmAddr = Get64(buf + 0x18, be);
|
||||
vmSize = Get64(buf + 0x20, be);
|
||||
phAddr = Get64(buf + 0x28, be);
|
||||
phSize = Get64(buf + 0x30, be);
|
||||
}
|
||||
else
|
||||
{
|
||||
vmAddr = Get32(buf + 0x18, be);
|
||||
vmSize = Get32(buf + 0x1C, be);
|
||||
phAddr = Get32(buf + 0x20, be);
|
||||
phSize = Get32(buf + 0x24, be);
|
||||
}
|
||||
{
|
||||
UInt64 totalSize = phAddr + phSize;
|
||||
if (totalSize > _totalSize)
|
||||
_totalSize = totalSize;
|
||||
}
|
||||
}
|
||||
|
||||
CSegment seg;
|
||||
memcpy(seg.Name, buf + 8, kNameSize);
|
||||
_segments.Add(seg);
|
||||
|
||||
UInt32 numSections = Get32(buf + offs - 8, be);
|
||||
if (numSections > (1 << 8))
|
||||
return false;
|
||||
|
||||
if (numSections == 0)
|
||||
{
|
||||
CSection section;
|
||||
section.IsDummy = true;
|
||||
section.SegmentIndex = _segments.Size() - 1;
|
||||
section.Va = vmAddr;
|
||||
section.PSize = phSize;
|
||||
section.VSize = vmSize;
|
||||
section.Pa = phAddr;
|
||||
section.Flags = 0;
|
||||
_sections.Add(section);
|
||||
}
|
||||
else do
|
||||
{
|
||||
CSection section;
|
||||
UInt32 headerSize = (cmd == MACH_CMD_SEGMENT_64) ? 0x50 : 0x44;
|
||||
const Byte *p = buf + offs;
|
||||
if (cmdSize - offs < headerSize)
|
||||
break;
|
||||
if (cmd == MACH_CMD_SEGMENT_64)
|
||||
{
|
||||
section.Va = Get64(p + 0x20, be);
|
||||
section.VSize = Get64(p + 0x28, be);
|
||||
section.Pa = Get32(p + 0x30, be);
|
||||
section.Flags = Get32(p + 0x40, be);
|
||||
}
|
||||
else
|
||||
{
|
||||
section.Va = Get32(p + 0x20, be);
|
||||
section.VSize = Get32(p + 0x24, be);
|
||||
section.Pa = Get32(p + 0x28, be);
|
||||
section.Flags = Get32(p + 0x38, be);
|
||||
}
|
||||
if (section.Flags == MACH_SECT_ATTR_ZEROFILL)
|
||||
section.PSize = 0;
|
||||
else
|
||||
section.PSize = section.VSize;
|
||||
memcpy(section.Name, p, kNameSize);
|
||||
memcpy(section.SegName, p + kNameSize, kNameSize);
|
||||
section.SegmentIndex = _segments.Size() - 1;
|
||||
_sections.Add(section);
|
||||
offs += headerSize;
|
||||
}
|
||||
while (--numSections);
|
||||
|
||||
if (offs != cmdSize)
|
||||
return false;
|
||||
}
|
||||
buf += cmdSize;
|
||||
size -= cmdSize;
|
||||
}
|
||||
_headersSize = (UInt32)(buf - bufStart);
|
||||
return reduceCommands || (size == 0);
|
||||
}
|
||||
|
||||
static STATPROPSTG kArcProps[] =
|
||||
{
|
||||
{ NULL, kpidCpu, VT_BSTR},
|
||||
{ NULL, kpidBit64, VT_BOOL},
|
||||
{ NULL, kpidBigEndian, VT_BOOL},
|
||||
{ NULL, kpidCharacts, VT_BSTR},
|
||||
{ NULL, kpidPhySize, VT_UI8},
|
||||
{ NULL, kpidHeadersSize, VT_UI4}
|
||||
kpidCpu,
|
||||
kpidBit64,
|
||||
kpidBigEndian,
|
||||
kpidCharacts,
|
||||
kpidHeadersSize
|
||||
};
|
||||
|
||||
static STATPROPSTG kProps[] =
|
||||
static const Byte kProps[] =
|
||||
{
|
||||
{ NULL, kpidPath, VT_BSTR},
|
||||
{ NULL, kpidSize, VT_UI8},
|
||||
{ NULL, kpidPackSize, VT_UI8},
|
||||
{ NULL, kpidCharacts, VT_BSTR},
|
||||
{ NULL, kpidOffset, VT_UI8},
|
||||
{ NULL, kpidVa, VT_UI8}
|
||||
kpidPath,
|
||||
kpidSize,
|
||||
kpidPackSize,
|
||||
kpidCharacts,
|
||||
kpidOffset,
|
||||
kpidVa
|
||||
};
|
||||
|
||||
IMP_IInArchive_Props
|
||||
@@ -315,15 +246,94 @@ IMP_IInArchive_ArcProps
|
||||
STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
NCOM::CPropVariant prop;
|
||||
switch(propID)
|
||||
CPropVariant prop;
|
||||
switch (propID)
|
||||
{
|
||||
case kpidCpu: PAIR_TO_PROP(g_MachinePairs, _machine, prop); break;
|
||||
case kpidCharacts: TYPE_TO_PROP(g_FileTypes, _type, prop); break;
|
||||
case kpidShortComment:
|
||||
case kpidCpu:
|
||||
{
|
||||
AString s;
|
||||
char temp[16];
|
||||
UInt32 cpu = _cpuType & ~(UInt32)CPU_ARCH_ABI64;
|
||||
if (_cpuType == CPU_TYPE_AMD64)
|
||||
s = "x64";
|
||||
else
|
||||
{
|
||||
const char *n = NULL;
|
||||
for (unsigned i = 0; i < ARRAY_SIZE(g_CpuPairs); i++)
|
||||
{
|
||||
const CUInt32PCharPair &pair = g_CpuPairs[i];
|
||||
if (pair.Value == cpu)
|
||||
{
|
||||
n = pair.Name;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!n)
|
||||
{
|
||||
ConvertUInt32ToString(cpu, temp);
|
||||
n = temp;
|
||||
}
|
||||
s = n;
|
||||
|
||||
if (_cpuType & CPU_ARCH_ABI64)
|
||||
s += " 64-bit";
|
||||
else if (_cpuSubType & CPU_SUBTYPE_LIB64)
|
||||
s += " 64-bit lib";
|
||||
}
|
||||
UInt32 t = _cpuSubType & ~(UInt32)CPU_SUBTYPE_LIB64;
|
||||
if (t != 0 && (t != CPU_SUBTYPE_I386_ALL || cpu != CPU_TYPE_386))
|
||||
{
|
||||
const char *n = NULL;
|
||||
if (cpu == CPU_TYPE_PPC)
|
||||
{
|
||||
if (t == CPU_SUBTYPE_POWERPC_970)
|
||||
n = "970";
|
||||
else if (t < ARRAY_SIZE(k_PowerPc_SubTypes))
|
||||
n = k_PowerPc_SubTypes[t];
|
||||
}
|
||||
if (!n)
|
||||
{
|
||||
ConvertUInt32ToString(t, temp);
|
||||
n = temp;
|
||||
}
|
||||
s += ' ';
|
||||
s += n;
|
||||
}
|
||||
prop = s;
|
||||
break;
|
||||
}
|
||||
case kpidCharacts:
|
||||
{
|
||||
// TYPE_TO_PROP(g_FileTypes, _type, prop); break;
|
||||
AString res = TypeToString(g_FileTypes, ARRAY_SIZE(g_FileTypes), _type);
|
||||
AString s = FlagsToString(g_ArcFlags, ARRAY_SIZE(g_ArcFlags), _flags);
|
||||
if (!s.IsEmpty())
|
||||
{
|
||||
res += ' ';
|
||||
res += s;
|
||||
}
|
||||
prop = res;
|
||||
break;
|
||||
}
|
||||
case kpidPhySize: prop = _totalSize; break;
|
||||
case kpidHeadersSize: prop = _headersSize; break;
|
||||
case kpidBit64: if (_mode64) prop = _mode64; break;
|
||||
case kpidBigEndian: if (_be) prop = _be; break;
|
||||
case kpidExtension:
|
||||
{
|
||||
const char *ext = NULL;
|
||||
if (_type == kType_OBJECT)
|
||||
ext = "o";
|
||||
else if (_type == kType_BUNDLE)
|
||||
ext = "bundle";
|
||||
else if (_type == kType_DYLIB)
|
||||
ext = "dylib"; // main shared library usually does not have extension
|
||||
if (ext)
|
||||
prop = ext;
|
||||
break;
|
||||
}
|
||||
// case kpidIsSelfExe: prop = (_type == kType_EXECUTE); break;
|
||||
}
|
||||
prop.Detach(value);
|
||||
return S_OK;
|
||||
@@ -340,10 +350,8 @@ static AString GetName(const char *name)
|
||||
|
||||
static AString SectFlagsToString(UInt32 flags)
|
||||
{
|
||||
AString res = TypeToString(g_SectTypes, sizeof(g_SectTypes) / sizeof(g_SectTypes[0]),
|
||||
flags & MACH_SECT_TYPE_MASK);
|
||||
AString s = FlagsToString(g_Flags, sizeof(g_Flags) / sizeof(g_Flags[0]),
|
||||
flags & MACH_SECT_ATTR_MASK);
|
||||
AString res = TypeToString(g_SectTypes, ARRAY_SIZE(g_SectTypes), flags & SECT_TYPE_MASK);
|
||||
AString s = FlagsToString(g_Flags, ARRAY_SIZE(g_Flags), flags & SECT_ATTR_MASK);
|
||||
if (!s.IsEmpty())
|
||||
{
|
||||
res += ' ';
|
||||
@@ -355,21 +363,21 @@ static AString SectFlagsToString(UInt32 flags)
|
||||
STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
NCOM::CPropVariant prop;
|
||||
CPropVariant prop;
|
||||
const CSection &item = _sections[index];
|
||||
switch(propID)
|
||||
switch (propID)
|
||||
{
|
||||
case kpidPath:
|
||||
{
|
||||
AString s = GetName(_segments[item.SegmentIndex].Name);
|
||||
if (!item.IsDummy)
|
||||
s += GetName(item.Name);
|
||||
StringToProp(s, prop);
|
||||
prop = MultiByteToUnicodeString(s);
|
||||
break;
|
||||
}
|
||||
case kpidSize: /* prop = (UInt64)item.VSize; break; */
|
||||
case kpidPackSize: prop = (UInt64)item.GetPackSize(); break;
|
||||
case kpidCharacts: if (!item.IsDummy) StringToProp(SectFlagsToString(item.Flags), prop); break;
|
||||
case kpidCharacts: if (!item.IsDummy) prop = SectFlagsToString(item.Flags); break;
|
||||
case kpidOffset: prop = item.Pa; break;
|
||||
case kpidVa: prop = item.Va; break;
|
||||
}
|
||||
@@ -380,18 +388,12 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
|
||||
|
||||
HRESULT CHandler::Open2(ISequentialInStream *stream)
|
||||
{
|
||||
const UInt32 kBufSize = 1 << 18;
|
||||
const UInt32 kSigSize = 4;
|
||||
const UInt32 kStartHeaderSize = 7 * 4;
|
||||
|
||||
CByteBuffer buffer;
|
||||
buffer.SetCapacity(kBufSize);
|
||||
Byte *buf = buffer;
|
||||
|
||||
size_t processed = kSigSize;
|
||||
RINOK(ReadStream_FALSE(stream, buf, processed));
|
||||
UInt32 sig = GetUi32(buf);
|
||||
Byte header[kStartHeaderSize];
|
||||
RINOK(ReadStream_FALSE(stream, header, kStartHeaderSize));
|
||||
bool be, mode64;
|
||||
switch(sig)
|
||||
switch (GetUi32(header))
|
||||
{
|
||||
case 0xCEFAEDFE: be = true; mode64 = false; break;
|
||||
case 0xCFFAEDFE: be = true; mode64 = true; break;
|
||||
@@ -399,11 +401,148 @@ HRESULT CHandler::Open2(ISequentialInStream *stream)
|
||||
case 0xFEEDFACF: be = false; mode64 = true; break;
|
||||
default: return S_FALSE;
|
||||
}
|
||||
processed = kBufSize - kSigSize;
|
||||
RINOK(ReadStream(stream, buf + kSigSize, &processed));
|
||||
_mode64 = mode64;
|
||||
_be = be;
|
||||
return Parse(buf, (UInt32)processed + kSigSize) ? S_OK : S_FALSE;
|
||||
|
||||
UInt32 numCommands = Get32(header + 0x10, be);
|
||||
UInt32 commandsSize = Get32(header + 0x14, be);
|
||||
|
||||
if (numCommands == 0)
|
||||
return S_FALSE;
|
||||
|
||||
if (commandsSize > (1 << 24) ||
|
||||
numCommands > (1 << 21) ||
|
||||
numCommands * 8 > commandsSize)
|
||||
return S_FALSE;
|
||||
|
||||
_cpuType = Get32(header + 4, be);
|
||||
_cpuSubType = Get32(header + 8, be);
|
||||
_type = Get32(header + 0xC, be);
|
||||
_flags = Get32(header + 0x18, be);
|
||||
|
||||
/*
|
||||
// Probably the sections are in first commands. So we can reduce the number of commands.
|
||||
bool reduceCommands = false;
|
||||
const UInt32 kNumReduceCommands = 16;
|
||||
if (numCommands > kNumReduceCommands)
|
||||
{
|
||||
reduceCommands = true;
|
||||
numCommands = kNumReduceCommands;
|
||||
}
|
||||
*/
|
||||
|
||||
UInt32 startHeaderSize = kStartHeaderSize;
|
||||
if (mode64)
|
||||
startHeaderSize += 4;
|
||||
_headersSize = startHeaderSize + commandsSize;
|
||||
_totalSize = _headersSize;
|
||||
CByteArr buffer(_headersSize);
|
||||
RINOK(ReadStream_FALSE(stream, buffer + kStartHeaderSize, _headersSize - kStartHeaderSize));
|
||||
const Byte *buf = buffer + startHeaderSize;
|
||||
size_t size = _headersSize - startHeaderSize;
|
||||
for (UInt32 cmdIndex = 0; cmdIndex < numCommands; cmdIndex++)
|
||||
{
|
||||
if (size < 8)
|
||||
return S_FALSE;
|
||||
UInt32 cmd = Get32(buf, be);
|
||||
UInt32 cmdSize = Get32(buf + 4, be);
|
||||
if (cmdSize < 8)
|
||||
return S_FALSE;
|
||||
if (size < cmdSize)
|
||||
return S_FALSE;
|
||||
if (cmd == CMD_SEGMENT_32 || cmd == CMD_SEGMENT_64)
|
||||
{
|
||||
UInt32 offs = (cmd == CMD_SEGMENT_64) ? 0x48 : 0x38;
|
||||
if (cmdSize < offs)
|
||||
break;
|
||||
|
||||
UInt64 vmAddr, vmSize, phAddr, phSize;
|
||||
|
||||
{
|
||||
if (cmd == CMD_SEGMENT_64)
|
||||
{
|
||||
vmAddr = Get64(buf + 0x18, be);
|
||||
vmSize = Get64(buf + 0x20, be);
|
||||
phAddr = Get64(buf + 0x28, be);
|
||||
phSize = Get64(buf + 0x30, be);
|
||||
}
|
||||
else
|
||||
{
|
||||
vmAddr = Get32(buf + 0x18, be);
|
||||
vmSize = Get32(buf + 0x1C, be);
|
||||
phAddr = Get32(buf + 0x20, be);
|
||||
phSize = Get32(buf + 0x24, be);
|
||||
}
|
||||
{
|
||||
UInt64 totalSize = phAddr + phSize;
|
||||
if (totalSize < phAddr)
|
||||
return S_FALSE;
|
||||
if (_totalSize < totalSize)
|
||||
_totalSize = totalSize;
|
||||
}
|
||||
}
|
||||
|
||||
CSegment seg;
|
||||
memcpy(seg.Name, buf + 8, kNameSize);
|
||||
_segments.Add(seg);
|
||||
|
||||
UInt32 numSections = Get32(buf + offs - 8, be);
|
||||
if (numSections > (1 << 8))
|
||||
return S_FALSE;
|
||||
|
||||
if (numSections == 0)
|
||||
{
|
||||
CSection § = _sections.AddNew();
|
||||
sect.IsDummy = true;
|
||||
sect.SegmentIndex = _segments.Size() - 1;
|
||||
sect.Va = vmAddr;
|
||||
sect.PSize = phSize;
|
||||
sect.VSize = vmSize;
|
||||
sect.Pa = phAddr;
|
||||
sect.Flags = 0;
|
||||
}
|
||||
else do
|
||||
{
|
||||
UInt32 headSize = (cmd == CMD_SEGMENT_64) ? 0x50 : 0x44;
|
||||
const Byte *p = buf + offs;
|
||||
if (cmdSize - offs < headSize)
|
||||
break;
|
||||
CSection § = _sections.AddNew();
|
||||
unsigned f32Offset;
|
||||
if (cmd == CMD_SEGMENT_64)
|
||||
{
|
||||
sect.Va = Get64(p + 0x20, be);
|
||||
sect.VSize = Get64(p + 0x28, be);
|
||||
f32Offset = 0x30;
|
||||
}
|
||||
else
|
||||
{
|
||||
sect.Va = Get32(p + 0x20, be);
|
||||
sect.VSize = Get32(p + 0x24, be);
|
||||
f32Offset = 0x28;
|
||||
}
|
||||
sect.Pa = Get32(p + f32Offset, be);
|
||||
sect.Flags = Get32(p + f32Offset + 10, be);
|
||||
if (sect.Flags == SECT_ATTR_ZEROFILL)
|
||||
sect.PSize = 0;
|
||||
else
|
||||
sect.PSize = sect.VSize;
|
||||
memcpy(sect.Name, p, kNameSize);
|
||||
memcpy(sect.SegName, p + kNameSize, kNameSize);
|
||||
sect.SegmentIndex = _segments.Size() - 1;
|
||||
offs += headSize;
|
||||
}
|
||||
while (--numSections);
|
||||
|
||||
if (offs != cmdSize)
|
||||
return S_FALSE;
|
||||
}
|
||||
buf += cmdSize;
|
||||
size -= cmdSize;
|
||||
}
|
||||
// return (reduceCommands || (size == 0)) ? S_OK : S_FALSE;
|
||||
if (size != 0)
|
||||
return S_FALSE;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CHandler::Open(IInStream *inStream,
|
||||
@@ -413,6 +552,13 @@ STDMETHODIMP CHandler::Open(IInStream *inStream,
|
||||
COM_TRY_BEGIN
|
||||
Close();
|
||||
RINOK(Open2(inStream));
|
||||
if (!_allowTail)
|
||||
{
|
||||
UInt64 fileSize;
|
||||
RINOK(inStream->Seek(0, STREAM_SEEK_END, &fileSize));
|
||||
if (fileSize > _totalSize)
|
||||
return S_FALSE;
|
||||
}
|
||||
_inStream = inStream;
|
||||
return S_OK;
|
||||
COM_TRY_END
|
||||
@@ -420,6 +566,7 @@ STDMETHODIMP CHandler::Open(IInStream *inStream,
|
||||
|
||||
STDMETHODIMP CHandler::Close()
|
||||
{
|
||||
_totalSize = 0;
|
||||
_inStream.Release();
|
||||
_sections.Clear();
|
||||
_segments.Clear();
|
||||
@@ -436,7 +583,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
Int32 testMode, IArchiveExtractCallback *extractCallback)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
bool allFilesMode = (numItems == (UInt32)-1);
|
||||
bool allFilesMode = (numItems == (UInt32)(Int32)-1);
|
||||
if (allFilesMode)
|
||||
numItems = _sections.Size();
|
||||
if (numItems == 0)
|
||||
@@ -490,10 +637,27 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
static IInArchive *CreateArc() { return new CHandler; }
|
||||
STDMETHODIMP CHandler::AllowTail(Int32 allowTail)
|
||||
{
|
||||
_allowTail = IntToBool(allowTail);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
IMP_CreateArcIn
|
||||
|
||||
#define k_Signature { \
|
||||
4, 0xCE, 0xFA, 0xED, 0xFE, \
|
||||
4, 0xCF, 0xFA, 0xED, 0xFE, \
|
||||
4, 0xFE, 0xED, 0xFA, 0xCE, \
|
||||
4, 0xFE, 0xED, 0xFA, 0xCF }
|
||||
|
||||
static CArcInfo g_ArcInfo =
|
||||
{ L"MachO", L"", 0, 0xDF, { 0 }, 0, false, CreateArc, 0 };
|
||||
{ "MachO", "macho", 0, 0xDF,
|
||||
4 * 5, k_Signature,
|
||||
0,
|
||||
NArcInfoFlags::kMultiSignature |
|
||||
NArcInfoFlags::kPreArc,
|
||||
CreateArc };
|
||||
|
||||
REGISTER_ARC(Macho)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user