diff options
Diffstat (limited to 'CPP/7zip/Archive/ElfHandler.cpp')
-rw-r--r-- | CPP/7zip/Archive/ElfHandler.cpp | 113 |
1 files changed, 56 insertions, 57 deletions
diff --git a/CPP/7zip/Archive/ElfHandler.cpp b/CPP/7zip/Archive/ElfHandler.cpp index efcde95..7e1facc 100644 --- a/CPP/7zip/Archive/ElfHandler.cpp +++ b/CPP/7zip/Archive/ElfHandler.cpp | |||
@@ -156,18 +156,22 @@ bool CHeader::Parse(const Byte *p) | |||
156 | 156 | ||
157 | #define PT_PHDR 6 | 157 | #define PT_PHDR 6 |
158 | 158 | ||
159 | static const char * const g_SegnmentTypes[] = | 159 | static const CUInt32PCharPair g_SegnmentTypes[] = |
160 | { | 160 | { |
161 | "Unused" | 161 | { 0, "Unused" }, |
162 | , "Loadable segment" | 162 | { 1, "Loadable segment" }, |
163 | , "Dynamic linking tables" | 163 | { 2, "Dynamic linking tables" }, |
164 | , "Program interpreter path name" | 164 | { 3, "Program interpreter path name" }, |
165 | , "Note section" | 165 | { 4, "Note section" }, |
166 | , "SHLIB" | 166 | { 5, "SHLIB" }, |
167 | , "Program header table" | 167 | { 6, "Program header table" }, |
168 | , "TLS" | 168 | { 7, "TLS" }, |
169 | { 0x6474e550, "GNU_EH_FRAME" }, | ||
170 | { 0x6474e551, "GNU_STACK" }, | ||
171 | { 0x6474e552, "GNU_RELRO" } | ||
169 | }; | 172 | }; |
170 | 173 | ||
174 | |||
171 | static const char * const g_SegmentFlags[] = | 175 | static const char * const g_SegmentFlags[] = |
172 | { | 176 | { |
173 | "Execute" | 177 | "Execute" |
@@ -271,6 +275,7 @@ static const CUInt32PCharPair g_SectTypes[] = | |||
271 | { 16, "PREINIT_ARRAY" }, | 275 | { 16, "PREINIT_ARRAY" }, |
272 | { 17, "GROUP" }, | 276 | { 17, "GROUP" }, |
273 | { 18, "SYMTAB_SHNDX" }, | 277 | { 18, "SYMTAB_SHNDX" }, |
278 | |||
274 | { 0x6ffffff5, "GNU_ATTRIBUTES" }, | 279 | { 0x6ffffff5, "GNU_ATTRIBUTES" }, |
275 | { 0x6ffffff6, "GNU_HASH" }, | 280 | { 0x6ffffff6, "GNU_HASH" }, |
276 | { 0x6ffffffd, "GNU_verdef" }, | 281 | { 0x6ffffffd, "GNU_verdef" }, |
@@ -654,11 +659,9 @@ static const char * const g_Types[] = | |||
654 | 659 | ||
655 | 660 | ||
656 | 661 | ||
657 | class CHandler: | 662 | Z7_CLASS_IMP_CHandler_IInArchive_1( |
658 | public IInArchive, | 663 | IArchiveAllowTail |
659 | public IArchiveAllowTail, | 664 | ) |
660 | public CMyUnknownImp | ||
661 | { | ||
662 | CRecordVector<CSegment> _segments; | 665 | CRecordVector<CSegment> _segments; |
663 | CRecordVector<CSection> _sections; | 666 | CRecordVector<CSection> _sections; |
664 | CByteBuffer _namesData; | 667 | CByteBuffer _namesData; |
@@ -671,10 +674,6 @@ class CHandler: | |||
671 | void GetSectionName(UInt32 index, NCOM::CPropVariant &prop, bool showNULL) const; | 674 | void GetSectionName(UInt32 index, NCOM::CPropVariant &prop, bool showNULL) const; |
672 | HRESULT Open2(IInStream *stream); | 675 | HRESULT Open2(IInStream *stream); |
673 | public: | 676 | public: |
674 | MY_UNKNOWN_IMP2(IInArchive, IArchiveAllowTail) | ||
675 | INTERFACE_IInArchive(;) | ||
676 | STDMETHOD(AllowTail)(Int32 allowTail); | ||
677 | |||
678 | CHandler(): _allowTail(false) {} | 677 | CHandler(): _allowTail(false) {} |
679 | }; | 678 | }; |
680 | 679 | ||
@@ -683,7 +682,7 @@ void CHandler::GetSectionName(UInt32 index, NCOM::CPropVariant &prop, bool showN | |||
683 | if (index >= _sections.Size()) | 682 | if (index >= _sections.Size()) |
684 | return; | 683 | return; |
685 | const CSection §ion = _sections[index]; | 684 | const CSection §ion = _sections[index]; |
686 | UInt32 offset = section.Name; | 685 | const UInt32 offset = section.Name; |
687 | if (index == SHN_UNDEF /* && section.Type == SHT_NULL && offset == 0 */) | 686 | if (index == SHN_UNDEF /* && section.Type == SHT_NULL && offset == 0 */) |
688 | { | 687 | { |
689 | if (showNULL) | 688 | if (showNULL) |
@@ -732,7 +731,7 @@ static const CStatProp kProps[] = | |||
732 | IMP_IInArchive_Props_WITH_NAME | 731 | IMP_IInArchive_Props_WITH_NAME |
733 | IMP_IInArchive_ArcProps | 732 | IMP_IInArchive_ArcProps |
734 | 733 | ||
735 | STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) | 734 | Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)) |
736 | { | 735 | { |
737 | COM_TRY_BEGIN | 736 | COM_TRY_BEGIN |
738 | NCOM::CPropVariant prop; | 737 | NCOM::CPropVariant prop; |
@@ -747,27 +746,27 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) | |||
747 | case kpidCpu: | 746 | case kpidCpu: |
748 | { | 747 | { |
749 | AString s; | 748 | AString s; |
750 | if (_header.Machine < ARRAY_SIZE(g_Machines)) | 749 | if (_header.Machine < Z7_ARRAY_SIZE(g_Machines)) |
751 | { | 750 | { |
752 | const char *name = g_Machines[_header.Machine]; | 751 | const char *name = g_Machines[_header.Machine]; |
753 | if (name) | 752 | if (name) |
754 | s = name; | 753 | s = name; |
755 | } | 754 | } |
756 | if (s.IsEmpty()) | 755 | if (s.IsEmpty()) |
757 | s = TypePairToString(g_MachinePairs, ARRAY_SIZE(g_MachinePairs), _header.Machine); | 756 | s = TypePairToString(g_MachinePairs, Z7_ARRAY_SIZE(g_MachinePairs), _header.Machine); |
758 | UInt32 flags = _header.Flags; | 757 | UInt32 flags = _header.Flags; |
759 | if (flags != 0) | 758 | if (flags != 0) |
760 | { | 759 | { |
761 | s.Add_Space(); | 760 | s.Add_Space(); |
762 | if (_header.Machine == k_Machine_ARM) | 761 | if (_header.Machine == k_Machine_ARM) |
763 | { | 762 | { |
764 | s += FlagsToString(g_ARM_Flags, ARRAY_SIZE(g_ARM_Flags), flags & (((UInt32)1 << 24) - 1)); | 763 | s += FlagsToString(g_ARM_Flags, Z7_ARRAY_SIZE(g_ARM_Flags), flags & (((UInt32)1 << 24) - 1)); |
765 | s += " ABI:"; | 764 | s += " ABI:"; |
766 | s.Add_UInt32(flags >> 24); | 765 | s.Add_UInt32(flags >> 24); |
767 | } | 766 | } |
768 | else if (_header.Machine == k_Machine_MIPS) | 767 | else if (_header.Machine == k_Machine_MIPS) |
769 | { | 768 | { |
770 | UInt32 ver = flags >> 28; | 769 | const UInt32 ver = flags >> 28; |
771 | s += "v"; | 770 | s += "v"; |
772 | s.Add_UInt32(ver); | 771 | s.Add_UInt32(ver); |
773 | flags &= (((UInt32)1 << 28) - 1); | 772 | flags &= (((UInt32)1 << 28) - 1); |
@@ -781,7 +780,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) | |||
781 | flags &= ~((UInt32)7 << 12); | 780 | flags &= ~((UInt32)7 << 12); |
782 | 781 | ||
783 | s.Add_Space(); | 782 | s.Add_Space(); |
784 | s += FlagsToString(g_MIPS_Flags, ARRAY_SIZE(g_MIPS_Flags), flags); | 783 | s += FlagsToString(g_MIPS_Flags, Z7_ARRAY_SIZE(g_MIPS_Flags), flags); |
785 | } | 784 | } |
786 | else | 785 | else |
787 | { | 786 | { |
@@ -822,7 +821,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) | |||
822 | COM_TRY_END | 821 | COM_TRY_END |
823 | } | 822 | } |
824 | 823 | ||
825 | STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) | 824 | Z7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)) |
826 | { | 825 | { |
827 | COM_TRY_BEGIN | 826 | COM_TRY_BEGIN |
828 | NCOM::CPropVariant prop; | 827 | NCOM::CPropVariant prop; |
@@ -843,7 +842,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val | |||
843 | case kpidSize: | 842 | case kpidSize: |
844 | case kpidPackSize: prop = (UInt64)item.Size; break; | 843 | case kpidPackSize: prop = (UInt64)item.Size; break; |
845 | case kpidVirtualSize: prop = (UInt64)item.VSize; break; | 844 | case kpidVirtualSize: prop = (UInt64)item.VSize; break; |
846 | case kpidType: TYPE_TO_PROP(g_SegnmentTypes, item.Type, prop); break; | 845 | case kpidType: PAIR_TO_PROP(g_SegnmentTypes, item.Type, prop); break; |
847 | case kpidCharacts: FLAGS_TO_PROP(g_SegmentFlags, item.Flags, prop); break; | 846 | case kpidCharacts: FLAGS_TO_PROP(g_SegmentFlags, item.Flags, prop); break; |
848 | 847 | ||
849 | } | 848 | } |
@@ -875,7 +874,7 @@ HRESULT CHandler::Open2(IInStream *stream) | |||
875 | { | 874 | { |
876 | const UInt32 kStartSize = kHeaderSize64; | 875 | const UInt32 kStartSize = kHeaderSize64; |
877 | Byte h[kStartSize]; | 876 | Byte h[kStartSize]; |
878 | RINOK(ReadStream_FALSE(stream, h, kStartSize)); | 877 | RINOK(ReadStream_FALSE(stream, h, kStartSize)) |
879 | if (h[0] != 0x7F || h[1] != 'E' || h[2] != 'L' || h[3] != 'F') | 878 | if (h[0] != 0x7F || h[1] != 'E' || h[2] != 'L' || h[3] != 'F') |
880 | return S_FALSE; | 879 | return S_FALSE; |
881 | if (!_header.Parse(h)) | 880 | if (!_header.Parse(h)) |
@@ -894,14 +893,14 @@ HRESULT CHandler::Open2(IInStream *stream) | |||
894 | if (_header.NumSegments != 0) | 893 | if (_header.NumSegments != 0) |
895 | { | 894 | { |
896 | if (_header.ProgOffset > (UInt64)1 << 60) return S_FALSE; | 895 | if (_header.ProgOffset > (UInt64)1 << 60) return S_FALSE; |
897 | RINOK(stream->Seek(_header.ProgOffset, STREAM_SEEK_SET, NULL)); | 896 | RINOK(InStream_SeekSet(stream, _header.ProgOffset)) |
898 | size_t size = (size_t)_header.SegmentEntrySize * _header.NumSegments; | 897 | const size_t size = (size_t)_header.SegmentEntrySize * _header.NumSegments; |
899 | 898 | ||
900 | CByteArr buf(size); | 899 | CByteArr buf(size); |
901 | 900 | ||
902 | RINOK(ReadStream_FALSE(stream, buf, size)); | 901 | RINOK(ReadStream_FALSE(stream, buf, size)) |
903 | 902 | ||
904 | UInt64 total = _header.ProgOffset + size; | 903 | const UInt64 total = _header.ProgOffset + size; |
905 | if (_totalSize < total) | 904 | if (_totalSize < total) |
906 | _totalSize = total; | 905 | _totalSize = total; |
907 | 906 | ||
@@ -923,12 +922,12 @@ HRESULT CHandler::Open2(IInStream *stream) | |||
923 | if (_header.NumSections != 0) | 922 | if (_header.NumSections != 0) |
924 | { | 923 | { |
925 | if (_header.SectOffset > (UInt64)1 << 60) return S_FALSE; | 924 | if (_header.SectOffset > (UInt64)1 << 60) return S_FALSE; |
926 | RINOK(stream->Seek(_header.SectOffset, STREAM_SEEK_SET, NULL)); | 925 | RINOK(InStream_SeekSet(stream, _header.SectOffset)) |
927 | size_t size = (size_t)_header.SectionEntrySize * _header.NumSections; | 926 | size_t size = (size_t)_header.SectionEntrySize * _header.NumSections; |
928 | 927 | ||
929 | CByteArr buf(size); | 928 | CByteArr buf(size); |
930 | 929 | ||
931 | RINOK(ReadStream_FALSE(stream, buf, size)); | 930 | RINOK(ReadStream_FALSE(stream, buf, size)) |
932 | 931 | ||
933 | UInt64 total = _header.SectOffset + size; | 932 | UInt64 total = _header.SectOffset + size; |
934 | if (_totalSize < total) | 933 | if (_totalSize < total) |
@@ -957,14 +956,14 @@ HRESULT CHandler::Open2(IInStream *stream) | |||
957 | if (_header.NamesSectIndex < _sections.Size()) | 956 | if (_header.NamesSectIndex < _sections.Size()) |
958 | { | 957 | { |
959 | const CSection § = _sections[_header.NamesSectIndex]; | 958 | const CSection § = _sections[_header.NamesSectIndex]; |
960 | UInt64 size = sect.GetSize(); | 959 | const UInt64 size = sect.GetSize(); |
961 | if (size != 0 | 960 | if (size != 0 |
962 | && size < ((UInt64)1 << 31) | 961 | && size < ((UInt64)1 << 31) |
963 | && (Int64)sect.Offset >= 0) | 962 | && (Int64)sect.Offset >= 0) |
964 | { | 963 | { |
965 | _namesData.Alloc((size_t)size); | 964 | _namesData.Alloc((size_t)size); |
966 | RINOK(stream->Seek(sect.Offset, STREAM_SEEK_SET, NULL)); | 965 | RINOK(InStream_SeekSet(stream, sect.Offset)) |
967 | RINOK(ReadStream_FALSE(stream, _namesData, (size_t)size)); | 966 | RINOK(ReadStream_FALSE(stream, _namesData, (size_t)size)) |
968 | } | 967 | } |
969 | } | 968 | } |
970 | 969 | ||
@@ -979,7 +978,7 @@ HRESULT CHandler::Open2(IInStream *stream) | |||
979 | if (!_allowTail) | 978 | if (!_allowTail) |
980 | { | 979 | { |
981 | UInt64 fileSize; | 980 | UInt64 fileSize; |
982 | RINOK(stream->Seek(0, STREAM_SEEK_END, &fileSize)); | 981 | RINOK(InStream_GetSize_SeekToEnd(stream, fileSize)) |
983 | if (fileSize > _totalSize) | 982 | if (fileSize > _totalSize) |
984 | return S_FALSE; | 983 | return S_FALSE; |
985 | } | 984 | } |
@@ -987,19 +986,19 @@ HRESULT CHandler::Open2(IInStream *stream) | |||
987 | return S_OK; | 986 | return S_OK; |
988 | } | 987 | } |
989 | 988 | ||
990 | STDMETHODIMP CHandler::Open(IInStream *inStream, | 989 | Z7_COM7F_IMF(CHandler::Open(IInStream *inStream, |
991 | const UInt64 * /* maxCheckStartPosition */, | 990 | const UInt64 * /* maxCheckStartPosition */, |
992 | IArchiveOpenCallback * /* openArchiveCallback */) | 991 | IArchiveOpenCallback * /* openArchiveCallback */)) |
993 | { | 992 | { |
994 | COM_TRY_BEGIN | 993 | COM_TRY_BEGIN |
995 | Close(); | 994 | Close(); |
996 | RINOK(Open2(inStream)); | 995 | RINOK(Open2(inStream)) |
997 | _inStream = inStream; | 996 | _inStream = inStream; |
998 | return S_OK; | 997 | return S_OK; |
999 | COM_TRY_END | 998 | COM_TRY_END |
1000 | } | 999 | } |
1001 | 1000 | ||
1002 | STDMETHODIMP CHandler::Close() | 1001 | Z7_COM7F_IMF(CHandler::Close()) |
1003 | { | 1002 | { |
1004 | _totalSize = 0; | 1003 | _totalSize = 0; |
1005 | _headersError = false; | 1004 | _headersError = false; |
@@ -1011,17 +1010,17 @@ STDMETHODIMP CHandler::Close() | |||
1011 | return S_OK; | 1010 | return S_OK; |
1012 | } | 1011 | } |
1013 | 1012 | ||
1014 | STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) | 1013 | Z7_COM7F_IMF(CHandler::GetNumberOfItems(UInt32 *numItems)) |
1015 | { | 1014 | { |
1016 | *numItems = _segments.Size() + _sections.Size(); | 1015 | *numItems = _segments.Size() + _sections.Size(); |
1017 | return S_OK; | 1016 | return S_OK; |
1018 | } | 1017 | } |
1019 | 1018 | ||
1020 | STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, | 1019 | Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems, |
1021 | Int32 testMode, IArchiveExtractCallback *extractCallback) | 1020 | Int32 testMode, IArchiveExtractCallback *extractCallback)) |
1022 | { | 1021 | { |
1023 | COM_TRY_BEGIN | 1022 | COM_TRY_BEGIN |
1024 | bool allFilesMode = (numItems == (UInt32)(Int32)-1); | 1023 | const bool allFilesMode = (numItems == (UInt32)(Int32)-1); |
1025 | if (allFilesMode) | 1024 | if (allFilesMode) |
1026 | numItems = _segments.Size() + _sections.Size(); | 1025 | numItems = _segments.Size() + _sections.Size(); |
1027 | if (numItems == 0) | 1026 | if (numItems == 0) |
@@ -1030,7 +1029,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, | |||
1030 | UInt32 i; | 1029 | UInt32 i; |
1031 | for (i = 0; i < numItems; i++) | 1030 | for (i = 0; i < numItems; i++) |
1032 | { | 1031 | { |
1033 | UInt32 index = allFilesMode ? i : indices[i]; | 1032 | const UInt32 index = allFilesMode ? i : indices[i]; |
1034 | totalSize += (index < _segments.Size()) ? | 1033 | totalSize += (index < _segments.Size()) ? |
1035 | _segments[index].Size : | 1034 | _segments[index].Size : |
1036 | _sections[index - _segments.Size()].GetSize(); | 1035 | _sections[index - _segments.Size()].GetSize(); |
@@ -1054,11 +1053,11 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, | |||
1054 | for (i = 0; i < numItems; i++, currentTotalSize += currentItemSize) | 1053 | for (i = 0; i < numItems; i++, currentTotalSize += currentItemSize) |
1055 | { | 1054 | { |
1056 | lps->InSize = lps->OutSize = currentTotalSize; | 1055 | lps->InSize = lps->OutSize = currentTotalSize; |
1057 | RINOK(lps->SetCur()); | 1056 | RINOK(lps->SetCur()) |
1058 | Int32 askMode = testMode ? | 1057 | const Int32 askMode = testMode ? |
1059 | NExtract::NAskMode::kTest : | 1058 | NExtract::NAskMode::kTest : |
1060 | NExtract::NAskMode::kExtract; | 1059 | NExtract::NAskMode::kExtract; |
1061 | UInt32 index = allFilesMode ? i : indices[i]; | 1060 | const UInt32 index = allFilesMode ? i : indices[i]; |
1062 | UInt64 offset; | 1061 | UInt64 offset; |
1063 | if (index < _segments.Size()) | 1062 | if (index < _segments.Size()) |
1064 | { | 1063 | { |
@@ -1074,24 +1073,24 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, | |||
1074 | } | 1073 | } |
1075 | 1074 | ||
1076 | CMyComPtr<ISequentialOutStream> outStream; | 1075 | CMyComPtr<ISequentialOutStream> outStream; |
1077 | RINOK(extractCallback->GetStream(index, &outStream, askMode)); | 1076 | RINOK(extractCallback->GetStream(index, &outStream, askMode)) |
1078 | if (!testMode && !outStream) | 1077 | if (!testMode && !outStream) |
1079 | continue; | 1078 | continue; |
1080 | 1079 | ||
1081 | RINOK(extractCallback->PrepareOperation(askMode)); | 1080 | RINOK(extractCallback->PrepareOperation(askMode)) |
1082 | RINOK(_inStream->Seek(offset, STREAM_SEEK_SET, NULL)); | 1081 | RINOK(InStream_SeekSet(_inStream, offset)) |
1083 | streamSpec->Init(currentItemSize); | 1082 | streamSpec->Init(currentItemSize); |
1084 | RINOK(copyCoder->Code(inStream, outStream, NULL, NULL, progress)); | 1083 | RINOK(copyCoder->Code(inStream, outStream, NULL, NULL, progress)) |
1085 | outStream.Release(); | 1084 | outStream.Release(); |
1086 | RINOK(extractCallback->SetOperationResult(copyCoderSpec->TotalSize == currentItemSize ? | 1085 | RINOK(extractCallback->SetOperationResult(copyCoderSpec->TotalSize == currentItemSize ? |
1087 | NExtract::NOperationResult::kOK: | 1086 | NExtract::NOperationResult::kOK: |
1088 | NExtract::NOperationResult::kDataError)); | 1087 | NExtract::NOperationResult::kDataError)) |
1089 | } | 1088 | } |
1090 | return S_OK; | 1089 | return S_OK; |
1091 | COM_TRY_END | 1090 | COM_TRY_END |
1092 | } | 1091 | } |
1093 | 1092 | ||
1094 | STDMETHODIMP CHandler::AllowTail(Int32 allowTail) | 1093 | Z7_COM7F_IMF(CHandler::AllowTail(Int32 allowTail)) |
1095 | { | 1094 | { |
1096 | _allowTail = IntToBool(allowTail); | 1095 | _allowTail = IntToBool(allowTail); |
1097 | return S_OK; | 1096 | return S_OK; |
@@ -1100,7 +1099,7 @@ STDMETHODIMP CHandler::AllowTail(Int32 allowTail) | |||
1100 | static const Byte k_Signature[] = { 0x7F, 'E', 'L', 'F' }; | 1099 | static const Byte k_Signature[] = { 0x7F, 'E', 'L', 'F' }; |
1101 | 1100 | ||
1102 | REGISTER_ARC_I( | 1101 | REGISTER_ARC_I( |
1103 | "ELF", "elf", 0, 0xDE, | 1102 | "ELF", "elf", NULL, 0xDE, |
1104 | k_Signature, | 1103 | k_Signature, |
1105 | 0, | 1104 | 0, |
1106 | NArcInfoFlags::kPreArc, | 1105 | NArcInfoFlags::kPreArc, |