aboutsummaryrefslogtreecommitdiff
path: root/CPP/7zip/Archive/ElfHandler.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'CPP/7zip/Archive/ElfHandler.cpp')
-rw-r--r--CPP/7zip/Archive/ElfHandler.cpp113
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
159static const char * const g_SegnmentTypes[] = 159static 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
171static const char * const g_SegmentFlags[] = 175static 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
657class CHandler: 662Z7_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);
673public: 676public:
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 &section = _sections[index]; 684 const CSection &section = _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[] =
732IMP_IInArchive_Props_WITH_NAME 731IMP_IInArchive_Props_WITH_NAME
733IMP_IInArchive_ArcProps 732IMP_IInArchive_ArcProps
734 733
735STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) 734Z7_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
825STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) 824Z7_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 &sect = _sections[_header.NamesSectIndex]; 958 const CSection &sect = _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
990STDMETHODIMP CHandler::Open(IInStream *inStream, 989Z7_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
1002STDMETHODIMP CHandler::Close() 1001Z7_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
1014STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) 1013Z7_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
1020STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, 1019Z7_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
1094STDMETHODIMP CHandler::AllowTail(Int32 allowTail) 1093Z7_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)
1100static const Byte k_Signature[] = { 0x7F, 'E', 'L', 'F' }; 1099static const Byte k_Signature[] = { 0x7F, 'E', 'L', 'F' };
1101 1100
1102REGISTER_ARC_I( 1101REGISTER_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,