aboutsummaryrefslogtreecommitdiff
path: root/CPP/7zip/Archive/ElfHandler.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--CPP/7zip/Archive/ElfHandler.cpp318
1 files changed, 215 insertions, 103 deletions
diff --git a/CPP/7zip/Archive/ElfHandler.cpp b/CPP/7zip/Archive/ElfHandler.cpp
index e31b4ae..305173b 100644
--- a/CPP/7zip/Archive/ElfHandler.cpp
+++ b/CPP/7zip/Archive/ElfHandler.cpp
@@ -17,11 +17,13 @@
17 17
18#include "../Compress/CopyCoder.h" 18#include "../Compress/CopyCoder.h"
19 19
20// #define Z7_ELF_SHOW_DETAILS
21
20using namespace NWindows; 22using namespace NWindows;
21 23
22static UInt16 Get16(const Byte *p, bool be) { if (be) return GetBe16(p); return GetUi16(p); } 24static UInt16 Get16(const Byte *p, bool be) { if (be) return GetBe16a(p); return GetUi16a(p); }
23static UInt32 Get32(const Byte *p, bool be) { if (be) return GetBe32(p); return GetUi32(p); } 25static UInt32 Get32(const Byte *p, bool be) { if (be) return GetBe32a(p); return GetUi32a(p); }
24static UInt64 Get64(const Byte *p, bool be) { if (be) return GetBe64(p); return GetUi64(p); } 26static UInt64 Get64(const Byte *p, bool be) { if (be) return GetBe64a(p); return GetUi64a(p); }
25 27
26#define G16(offs, v) v = Get16(p + (offs), be) 28#define G16(offs, v) v = Get16(p + (offs), be)
27#define G32(offs, v) v = Get32(p + (offs), be) 29#define G32(offs, v) v = Get32(p + (offs), be)
@@ -31,14 +33,51 @@ namespace NArchive {
31namespace NElf { 33namespace NElf {
32 34
33/* 35/*
34 ELF Structure for most files (real order can be different): 36ELF Structure example:
35 Header 37{
36 Program (segment) header table (used at runtime) 38 Header
37 Segment1 (Section ... Section) 39 Program header table (is used at runtime) (list of segment metadata records)
38 Segment2 40 {
39 ... 41 Segment (Read)
40 SegmentN 42 Segment : PT_PHDR : header table itself
41 Section header table (the data for linking and relocation) 43 Segment : PT_INTERP
44 Segment : PT_NOTE
45 .rela.dyn (RELA, ALLOC)
46 Segment (Execute/Read)
47 .text section (PROGBITS, SHF_ALLOC | SHF_EXECINSTR)
48 Segment (Read)
49 .rodata (PROGBITS, SHF_ALLOC | SHF_WRITE)
50 Segment : PT_GNU_EH_FRAME
51 .eh_frame_hdr
52 .eh_frame
53 .gcc_except_table
54 ...
55 Segment (Write/Read) (VaSize > Size)
56 Segment (Read) : PT_GNU_RELRO
57 Segment (Write/Read)
58 .data
59 .bss (Size == 0) (VSize != 0)
60 }
61 .comment (VA == 0)
62 .shstrtab (VA == 0)
63 Section header table (the data for linking and relocation)
64}
65
66 Last top level segment contains .bss section that requires additional VA space.
67 So (VaSize > Size) for that segment.
68
69 Segments can be unsorted (by offset) in table.
70 Top level segments has Type=PT_LOAD : "Loadable segment".
71 Top level segments usually are aligned for page size (4 KB).
72 Another segments (non PT_LOAD segments) are inside PT_LOAD segments.
73
74 (VA-offset == 0) is possible for some sections and segments at the beginning of file.
75 (VA-offset == 4KB*N) for most sections and segments where (Size != 0),
76 (VA-offset != 4KB*N) for .bss section (last section), because (Size == 0),
77 and that section is not mapped from image file.
78 Some files contain additional "virtual" 4 KB page in VA space after
79 end of data of top level segments (PT_LOAD) before new top level segments.
80 So (VA-offset) value can increase by 4 KB step.
42*/ 81*/
43 82
44#define ELF_CLASS_32 1 83#define ELF_CLASS_32 1
@@ -47,14 +86,14 @@ namespace NElf {
47#define ELF_DATA_2LSB 1 86#define ELF_DATA_2LSB 1
48#define ELF_DATA_2MSB 2 87#define ELF_DATA_2MSB 2
49 88
50static const UInt32 kHeaderSize32 = 0x34; 89static const unsigned kHeaderSize32 = 0x34;
51static const UInt32 kHeaderSize64 = 0x40; 90static const unsigned kHeaderSize64 = 0x40;
52 91
53static const UInt32 kSegmentSize32 = 0x20; 92static const unsigned kSegmentSize32 = 0x20;
54static const UInt32 kSegmentSize64 = 0x38; 93static const unsigned kSegmentSize64 = 0x38;
55 94
56static const UInt32 kSectionSize32 = 0x28; 95static const unsigned kSectionSize32 = 0x28;
57static const UInt32 kSectionSize64 = 0x40; 96static const unsigned kSectionSize64 = 0x40;
58 97
59struct CHeader 98struct CHeader
60{ 99{
@@ -78,9 +117,9 @@ struct CHeader
78 UInt16 NumSections; 117 UInt16 NumSections;
79 UInt16 NamesSectIndex; 118 UInt16 NamesSectIndex;
80 119
81 bool Parse(const Byte *buf); 120 bool Parse(const Byte *p);
82 121
83 UInt64 GetHeadersSize() const { return (UInt64)HeaderSize + 122 UInt32 GetHeadersSize() const { return (UInt32)HeaderSize +
84 (UInt32)NumSegments * SegmentEntrySize + 123 (UInt32)NumSegments * SegmentEntrySize +
85 (UInt32)NumSections * SectionEntrySize; } 124 (UInt32)NumSections * SectionEntrySize; }
86}; 125};
@@ -104,7 +143,7 @@ bool CHeader::Parse(const Byte *p)
104 if (p[6] != 1) // Version 143 if (p[6] != 1) // Version
105 return false; 144 return false;
106 Os = p[7]; 145 Os = p[7];
107 AbiVer = p[8]; 146 // AbiVer = p[8];
108 for (int i = 9; i < 16; i++) 147 for (int i = 9; i < 16; i++)
109 if (p[i] != 0) 148 if (p[i] != 0)
110 return false; 149 return false;
@@ -117,16 +156,21 @@ bool CHeader::Parse(const Byte *p)
117 if (Mode64) 156 if (Mode64)
118 { 157 {
119 // G64(0x18, EntryVa); 158 // G64(0x18, EntryVa);
120 G64(0x20, ProgOffset); 159 G64(0x20, ProgOffset); // == kHeaderSize64 == 0x40 usually
121 G64(0x28, SectOffset); 160 G64(0x28, SectOffset);
122 p += 0x30; 161 p += 0x30;
162 // we expect that fields are aligned
163 if (ProgOffset & 7) return false;
164 if (SectOffset & 7) return false;
123 } 165 }
124 else 166 else
125 { 167 {
126 // G32(0x18, EntryVa); 168 // G32(0x18, EntryVa);
127 G32(0x1C, ProgOffset); 169 G32(0x1C, ProgOffset); // == kHeaderSize32 == 0x34 usually
128 G32(0x20, SectOffset); 170 G32(0x20, SectOffset);
129 p += 0x24; 171 p += 0x24;
172 if (ProgOffset & 3) return false;
173 if (SectOffset & 3) return false;
130 } 174 }
131 175
132 G32(0, Flags); 176 G32(0, Flags);
@@ -140,21 +184,20 @@ bool CHeader::Parse(const Byte *p)
140 G16(12, NumSections); 184 G16(12, NumSections);
141 G16(14, NamesSectIndex); 185 G16(14, NamesSectIndex);
142 186
143 if (ProgOffset < HeaderSize && (ProgOffset != 0 || NumSegments != 0)) return false; 187 if (ProgOffset < HeaderSize && (ProgOffset || NumSegments)) return false;
144 if (SectOffset < HeaderSize && (SectOffset != 0 || NumSections != 0)) return false; 188 if (SectOffset < HeaderSize && (SectOffset || NumSections)) return false;
145 189
146 if (SegmentEntrySize == 0) { if (NumSegments != 0) return false; } 190 if (SegmentEntrySize == 0) { if (NumSegments) return false; }
147 else if (SegmentEntrySize != (Mode64 ? kSegmentSize64 : kSegmentSize32)) return false; 191 else if (SegmentEntrySize != (Mode64 ? kSegmentSize64 : kSegmentSize32)) return false;
148 192
149 if (SectionEntrySize == 0) { if (NumSections != 0) return false; } 193 if (SectionEntrySize == 0) { if (NumSections) return false; }
150 else if (SectionEntrySize != (Mode64 ? kSectionSize64 : kSectionSize32)) return false; 194 else if (SectionEntrySize != (Mode64 ? kSectionSize64 : kSectionSize32)) return false;
151 195
152 return true; 196 return true;
153} 197}
154 198
155// The program header table itself.
156 199
157#define PT_PHDR 6 200#define PT_PHDR 6 // The program header table itself.
158#define PT_GNU_STACK 0x6474e551 201#define PT_GNU_STACK 0x6474e551
159 202
160static const CUInt32PCharPair g_SegnmentTypes[] = 203static const CUInt32PCharPair g_SegnmentTypes[] =
@@ -186,16 +229,18 @@ struct CSegment
186 UInt32 Flags; 229 UInt32 Flags;
187 UInt64 Offset; 230 UInt64 Offset;
188 UInt64 Va; 231 UInt64 Va;
189 // UInt64 Pa; 232 UInt64 Size; // size in file
190 UInt64 Size; 233 UInt64 VSize; // size in memory
191 UInt64 VSize; 234#ifdef Z7_ELF_SHOW_DETAILS
192 UInt64 Align; 235 UInt64 Pa; // usually == Va, or == 0
193 236 UInt64 Align; // if (Align != 0), condition must be met:
237 // (VSize % Align == Offset % Alig)
238#endif
194 void UpdateTotalSize(UInt64 &totalSize) 239 void UpdateTotalSize(UInt64 &totalSize)
195 { 240 {
196 UInt64 t = Offset + Size; 241 const UInt64 t = Offset + Size;
197 if (totalSize < t) 242 if (totalSize < t)
198 totalSize = t; 243 totalSize = t;
199 } 244 }
200 void Parse(const Byte *p, bool mode64, bool be); 245 void Parse(const Byte *p, bool mode64, bool be);
201}; 246};
@@ -208,20 +253,24 @@ void CSegment::Parse(const Byte *p, bool mode64, bool be)
208 G32(4, Flags); 253 G32(4, Flags);
209 G64(8, Offset); 254 G64(8, Offset);
210 G64(0x10, Va); 255 G64(0x10, Va);
211 // G64(0x18, Pa);
212 G64(0x20, Size); 256 G64(0x20, Size);
213 G64(0x28, VSize); 257 G64(0x28, VSize);
258#ifdef Z7_ELF_SHOW_DETAILS
259 G64(0x18, Pa);
214 G64(0x30, Align); 260 G64(0x30, Align);
261#endif
215 } 262 }
216 else 263 else
217 { 264 {
218 G32(4, Offset); 265 G32(4, Offset);
219 G32(8, Va); 266 G32(8, Va);
220 // G32(0x0C, Pa);
221 G32(0x10, Size); 267 G32(0x10, Size);
222 G32(0x14, VSize); 268 G32(0x14, VSize);
223 G32(0x18, Flags); 269 G32(0x18, Flags);
270#ifdef Z7_ELF_SHOW_DETAILS
271 G32(0x0C, Pa);
224 G32(0x1C, Align); 272 G32(0x1C, Align);
273#endif
225 } 274 }
226} 275}
227 276
@@ -290,6 +339,8 @@ static const CUInt32PCharPair g_SectTypes[] =
290 { 0x70000005, "ARM_OVERLAYSECTION" } 339 { 0x70000005, "ARM_OVERLAYSECTION" }
291}; 340};
292 341
342
343// SHF_ flags
293static const CUInt32PCharPair g_SectionFlags[] = 344static const CUInt32PCharPair g_SectionFlags[] =
294{ 345{
295 { 0, "WRITE" }, 346 { 0, "WRITE" },
@@ -303,7 +354,7 @@ static const CUInt32PCharPair g_SectionFlags[] =
303 { 8, "OS_NONCONFORMING" }, 354 { 8, "OS_NONCONFORMING" },
304 { 9, "GROUP" }, 355 { 9, "GROUP" },
305 { 10, "TLS" }, 356 { 10, "TLS" },
306 { 11, "CP_SECTION" }, 357 { 11, "COMPRESSED" },
307 { 12, "DP_SECTION" }, 358 { 12, "DP_SECTION" },
308 { 13, "XCORE_SHF_CP_SECTION" }, 359 { 13, "XCORE_SHF_CP_SECTION" },
309 { 28, "64_LARGE" }, 360 { 28, "64_LARGE" },
@@ -326,9 +377,9 @@ struct CSection
326 377
327 void UpdateTotalSize(UInt64 &totalSize) 378 void UpdateTotalSize(UInt64 &totalSize)
328 { 379 {
329 UInt64 t = Offset + GetSize(); 380 const UInt64 t = Offset + GetSize();
330 if (totalSize < t) 381 if (totalSize < t)
331 totalSize = t; 382 totalSize = t;
332 } 383 }
333 bool Parse(const Byte *p, bool mode64, bool be); 384 bool Parse(const Byte *p, bool mode64, bool be);
334}; 385};
@@ -412,7 +463,7 @@ static const char * const g_Machines[] =
412 , "TRW RH-32" 463 , "TRW RH-32"
413 , "Motorola RCE" 464 , "Motorola RCE"
414 , "ARM" 465 , "ARM"
415 , "Alpha" 466 , "Alpha-STD"
416 , "Hitachi SH" 467 , "Hitachi SH"
417 , "SPARC-V9" 468 , "SPARC-V9"
418 , "Siemens Tricore" 469 , "Siemens Tricore"
@@ -577,8 +628,8 @@ static const char * const g_Machines[] =
577static const CUInt32PCharPair g_MachinePairs[] = 628static const CUInt32PCharPair g_MachinePairs[] =
578{ 629{
579 { 243, "RISC-V" }, 630 { 243, "RISC-V" },
580 { 47787, "Xilinx MicroBlaze" } 631 { 0x9026, "Alpha" }, // EM_ALPHA_EXP, obsolete, (used by NetBSD/alpha) (written in the absence of an ABI)
581 // { 0x9026, "Alpha" } 632 { 0xbaab, "Xilinx MicroBlaze" }
582}; 633};
583 634
584static const CUInt32PCharPair g_OS[] = 635static const CUInt32PCharPair g_OS[] =
@@ -600,6 +651,8 @@ static const CUInt32PCharPair g_OS[] =
600 { 14, "HP NSK" }, 651 { 14, "HP NSK" },
601 { 15, "AROS" }, 652 { 15, "AROS" },
602 { 16, "FenixOS" }, 653 { 16, "FenixOS" },
654 { 17, "CloudABI" },
655 { 18, "OpenVOS" },
603 { 64, "Bare-metal TMS320C6000" }, 656 { 64, "Bare-metal TMS320C6000" },
604 { 65, "Linux TMS320C6000" }, 657 { 65, "Linux TMS320C6000" },
605 { 97, "ARM" }, 658 { 97, "ARM" },
@@ -693,23 +746,27 @@ public:
693void CHandler::GetSectionName(UInt32 index, NCOM::CPropVariant &prop, bool showNULL) const 746void CHandler::GetSectionName(UInt32 index, NCOM::CPropVariant &prop, bool showNULL) const
694{ 747{
695 if (index >= _sections.Size()) 748 if (index >= _sections.Size())
696 return; 749 prop = index; // it's possible for some file, but maybe it's ERROR case
697 const CSection &section = _sections[index]; 750 else
698 const UInt32 offset = section.Name;
699 if (index == SHN_UNDEF /* && section.Type == SHT_NULL && offset == 0 */)
700 { 751 {
701 if (showNULL) 752 const CSection &section = _sections[index];
702 prop = "NULL"; 753 const UInt32 offset = section.Name;
703 return; 754 if (index == SHN_UNDEF /* && section.Type == SHT_NULL && offset == 0 */)
704 }
705 const Byte *p = _namesData;
706 size_t size = _namesData.Size();
707 for (size_t i = offset; i < size; i++)
708 if (p[i] == 0)
709 { 755 {
710 prop = (const char *)(p + offset); 756 if (showNULL)
757 prop = "NULL";
711 return; 758 return;
712 } 759 }
760 const Byte *p = _namesData;
761 const size_t size = _namesData.Size();
762 for (size_t i = offset; i < size; i++)
763 if (p[i] == 0)
764 {
765 prop = (const char *)(p + offset);
766 return;
767 }
768 prop = "ERROR";
769 }
713} 770}
714 771
715static const Byte kArcProps[] = 772static const Byte kArcProps[] =
@@ -726,7 +783,14 @@ static const Byte kArcProps[] =
726enum 783enum
727{ 784{
728 kpidLinkSection = kpidUserDefined, 785 kpidLinkSection = kpidUserDefined,
729 kpidInfoSection 786 kpidInfoSection,
787 kpidEntrySize
788#ifdef Z7_ELF_SHOW_DETAILS
789 // , kpidAlign
790 , kpidPa
791 , kpidDelta
792 , kpidOffsetEnd
793#endif
730}; 794};
731 795
732static const CStatProp kProps[] = 796static const CStatProp kProps[] =
@@ -738,6 +802,14 @@ static const CStatProp kProps[] =
738 { NULL, kpidVa, VT_UI8 }, 802 { NULL, kpidVa, VT_UI8 },
739 { NULL, kpidType, VT_BSTR }, 803 { NULL, kpidType, VT_BSTR },
740 { NULL, kpidCharacts, VT_BSTR } 804 { NULL, kpidCharacts, VT_BSTR }
805#ifdef Z7_ELF_SHOW_DETAILS
806 // , { "Align", kpidAlign, VT_UI8 }
807 , { NULL, kpidClusterSize, VT_UI8 }
808 , { "PA", kpidPa, VT_UI8 }
809 , { "End offset", kpidOffsetEnd, VT_UI8 }
810 , { "Delta (VA-Offset)", kpidDelta, VT_UI8 }
811#endif
812 , { "Entry Size", kpidEntrySize, VT_UI8}
741 , { "Link Section", kpidLinkSection, VT_BSTR} 813 , { "Link Section", kpidLinkSection, VT_BSTR}
742 , { "Info Section", kpidInfoSection, VT_BSTR} 814 , { "Info Section", kpidInfoSection, VT_BSTR}
743}; 815};
@@ -769,7 +841,7 @@ Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))
769 if (s.IsEmpty()) 841 if (s.IsEmpty())
770 s = TypePairToString(g_MachinePairs, Z7_ARRAY_SIZE(g_MachinePairs), _header.Machine); 842 s = TypePairToString(g_MachinePairs, Z7_ARRAY_SIZE(g_MachinePairs), _header.Machine);
771 UInt32 flags = _header.Flags; 843 UInt32 flags = _header.Flags;
772 if (flags != 0) 844 if (flags)
773 { 845 {
774 s.Add_Space(); 846 s.Add_Space();
775 if (_header.Machine == k_Machine_ARM) 847 if (_header.Machine == k_Machine_ARM)
@@ -783,10 +855,10 @@ Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))
783 const UInt32 ver = flags >> 28; 855 const UInt32 ver = flags >> 28;
784 s += "v"; 856 s += "v";
785 s.Add_UInt32(ver); 857 s.Add_UInt32(ver);
786 flags &= (((UInt32)1 << 28) - 1); 858 flags &= ((UInt32)1 << 28) - 1;
787 859
788 UInt32 abi = (flags >> 12) & 7; 860 const UInt32 abi = (flags >> 12) & 7;
789 if (abi != 0) 861 if (abi)
790 { 862 {
791 s += " ABI:"; 863 s += " ABI:";
792 s.Add_UInt32(abi); 864 s.Add_UInt32(abi);
@@ -827,13 +899,39 @@ Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))
827 case kpidHostOS: PAIR_TO_PROP(g_OS, _header.Os, prop); break; 899 case kpidHostOS: PAIR_TO_PROP(g_OS, _header.Os, prop); break;
828 case kpidCharacts: TYPE_TO_PROP(g_Types, _header.Type, prop); break; 900 case kpidCharacts: TYPE_TO_PROP(g_Types, _header.Type, prop); break;
829 case kpidComment: 901 case kpidComment:
902 {
903 AString s;
830 if (_stackFlags_Defined) 904 if (_stackFlags_Defined)
831 { 905 {
832 AString s ("STACK: "); 906 s += "STACK: ";
833 s += FlagsToString(g_SegmentFlags, Z7_ARRAY_SIZE(g_SegmentFlags), _stackFlags); 907 s += FlagsToString(g_SegmentFlags, Z7_ARRAY_SIZE(g_SegmentFlags), _stackFlags);
834 prop = s; 908 s.Add_LF();
909 /*
910 if (_header.EntryVa)
911 {
912 s += "Entry point: 0x";
913 char temp[16 + 4];
914 ConvertUInt64ToHex(_header.EntryVa, temp);
915 s += temp;
916 s.Add_LF();
917 }
918 */
919 }
920 if (_header.NumSegments)
921 {
922 s += "Segments: ";
923 s.Add_UInt32(_header.NumSegments);
924 s.Add_LF();
925 }
926 if (_header.NumSections)
927 {
928 s += "Sections: ";
929 s.Add_UInt32(_header.NumSections);
930 s.Add_LF();
835 } 931 }
932 prop = s;
836 break; 933 break;
934 }
837 case kpidExtension: 935 case kpidExtension:
838 { 936 {
839 const char *s = NULL; 937 const char *s = NULL;
@@ -878,12 +976,17 @@ Z7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
878 } 976 }
879 case kpidOffset: prop = item.Offset; break; 977 case kpidOffset: prop = item.Offset; break;
880 case kpidVa: prop = item.Va; break; 978 case kpidVa: prop = item.Va; break;
979#ifdef Z7_ELF_SHOW_DETAILS
980 case kpidDelta: if (item.Va) { prop = item.Va - item.Offset; } break;
981 case kpidOffsetEnd: prop = item.Offset + item.Size; break;
982 case kpidPa: prop = item.Pa; break;
983 case kpidClusterSize: prop = item.Align; break;
984#endif
881 case kpidSize: 985 case kpidSize:
882 case kpidPackSize: prop = (UInt64)item.Size; break; 986 case kpidPackSize: prop = (UInt64)item.Size; break;
883 case kpidVirtualSize: prop = (UInt64)item.VSize; break; 987 case kpidVirtualSize: prop = (UInt64)item.VSize; break;
884 case kpidType: PAIR_TO_PROP(g_SegnmentTypes, item.Type, prop); break; 988 case kpidType: PAIR_TO_PROP(g_SegnmentTypes, item.Type, prop); break;
885 case kpidCharacts: FLAGS_TO_PROP(g_SegmentFlags, item.Flags, prop); break; 989 case kpidCharacts: FLAGS_TO_PROP(g_SegmentFlags, item.Flags, prop); break;
886
887 } 990 }
888 } 991 }
889 else 992 else
@@ -895,13 +998,19 @@ Z7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
895 case kpidPath: GetSectionName(index, prop, true); break; 998 case kpidPath: GetSectionName(index, prop, true); break;
896 case kpidOffset: prop = item.Offset; break; 999 case kpidOffset: prop = item.Offset; break;
897 case kpidVa: prop = item.Va; break; 1000 case kpidVa: prop = item.Va; break;
1001#ifdef Z7_ELF_SHOW_DETAILS
1002 case kpidDelta: if (item.Va) { prop = item.Va - item.Offset; } break;
1003 case kpidOffsetEnd: prop = item.Offset + item.GetSize(); break;
1004#endif
898 case kpidSize: 1005 case kpidSize:
899 case kpidPackSize: prop = (UInt64)(item.Type == SHT_NOBITS ? 0 : item.VSize); break; 1006 case kpidPackSize: prop = (UInt64)(item.Type == SHT_NOBITS ? 0 : item.VSize); break;
900 case kpidVirtualSize: prop = item.GetSize(); break; 1007 case kpidVirtualSize: prop = item.GetSize(); break;
901 case kpidType: PAIR_TO_PROP(g_SectTypes, item.Type, prop); break; 1008 case kpidType: PAIR_TO_PROP(g_SectTypes, item.Type, prop); break;
902 case kpidCharacts: FLAGS_TO_PROP(g_SectionFlags, (UInt32)item.Flags, prop); break; 1009 case kpidCharacts: FLAGS_TO_PROP(g_SectionFlags, (UInt32)item.Flags, prop); break;
1010 // case kpidAlign: prop = item.Align; break;
903 case kpidLinkSection: GetSectionName(item.Link, prop, false); break; 1011 case kpidLinkSection: GetSectionName(item.Link, prop, false); break;
904 case kpidInfoSection: GetSectionName(item.Info, prop, false); break; 1012 case kpidInfoSection: GetSectionName(item.Info, prop, false); break;
1013 case kpidEntrySize: prop = (UInt64)item.EntSize; break;
905 } 1014 }
906 } 1015 }
907 prop.Detach(value); 1016 prop.Detach(value);
@@ -911,42 +1020,46 @@ Z7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
911 1020
912HRESULT CHandler::Open2(IInStream *stream) 1021HRESULT CHandler::Open2(IInStream *stream)
913{ 1022{
914 const UInt32 kStartSize = kHeaderSize64; 1023 {
915 Byte h[kStartSize]; 1024 const UInt32 kStartSize = kHeaderSize64;
916 RINOK(ReadStream_FALSE(stream, h, kStartSize)) 1025 UInt64 h64[kStartSize / 8];
917 if (h[0] != 0x7F || h[1] != 'E' || h[2] != 'L' || h[3] != 'F') 1026 RINOK(ReadStream_FALSE(stream, h64, kStartSize))
918 return S_FALSE; 1027 const Byte *h = (const Byte *)(const void *)h64;
919 if (!_header.Parse(h)) 1028 if (GetUi32a(h) != 0x464c457f)
920 return S_FALSE; 1029 return S_FALSE;
1030 if (!_header.Parse(h))
1031 return S_FALSE;
1032 }
921 1033
922 _totalSize = _header.HeaderSize; 1034 _totalSize = _header.HeaderSize;
923 1035
924 bool addSegments = false; 1036 bool addSegments = false;
925 bool addSections = false; 1037 bool addSections = false;
926 1038 // first section usually is NULL (with zero offsets and zero sizes).
927 if (_header.NumSections > 1) 1039 if (_header.NumSegments == 0 || _header.NumSections > 1)
928 addSections = true; 1040 addSections = true;
929 else 1041 else
930 addSegments = true; 1042 addSegments = true;
1043#ifdef Z7_ELF_SHOW_DETAILS
1044 addSections = true;
1045 addSegments = true;
1046#endif
931 1047
932 if (_header.NumSegments != 0) 1048 if (_header.NumSegments)
933 { 1049 {
934 if (_header.ProgOffset > (UInt64)1 << 60) return S_FALSE; 1050 if (_header.ProgOffset > (UInt64)1 << 60) return S_FALSE;
935 RINOK(InStream_SeekSet(stream, _header.ProgOffset)) 1051 RINOK(InStream_SeekSet(stream, _header.ProgOffset))
936 const size_t size = (size_t)_header.SegmentEntrySize * _header.NumSegments; 1052 const size_t size = (size_t)_header.SegmentEntrySize * _header.NumSegments;
937
938 CByteArr buf(size); 1053 CByteArr buf(size);
939
940 RINOK(ReadStream_FALSE(stream, buf, size)) 1054 RINOK(ReadStream_FALSE(stream, buf, size))
941 1055 {
942 const UInt64 total = _header.ProgOffset + size; 1056 const UInt64 total = _header.ProgOffset + size;
943 if (_totalSize < total) 1057 if (_totalSize < total)
944 _totalSize = total; 1058 _totalSize = total;
945 1059 }
946 const Byte *p = buf;
947
948 if (addSegments) 1060 if (addSegments)
949 _segments.ClearAndReserve(_header.NumSegments); 1061 _segments.ClearAndReserve(_header.NumSegments);
1062 const Byte *p = buf;
950 for (unsigned i = 0; i < _header.NumSegments; i++, p += _header.SegmentEntrySize) 1063 for (unsigned i = 0; i < _header.NumSegments; i++, p += _header.SegmentEntrySize)
951 { 1064 {
952 CSegment seg; 1065 CSegment seg;
@@ -957,29 +1070,29 @@ HRESULT CHandler::Open2(IInStream *stream)
957 _stackFlags = seg.Flags; 1070 _stackFlags = seg.Flags;
958 _stackFlags_Defined = true; 1071 _stackFlags_Defined = true;
959 } 1072 }
960 if (addSegments && seg.Type != PT_PHDR) 1073 if (addSegments
1074 // we don't show program header table segment
1075 && seg.Type != PT_PHDR
1076 )
961 _segments.AddInReserved(seg); 1077 _segments.AddInReserved(seg);
962 } 1078 }
963 } 1079 }
964 1080
965 if (_header.NumSections != 0) 1081 if (_header.NumSections)
966 { 1082 {
967 if (_header.SectOffset > (UInt64)1 << 60) return S_FALSE; 1083 if (_header.SectOffset > (UInt64)1 << 60) return S_FALSE;
968 RINOK(InStream_SeekSet(stream, _header.SectOffset)) 1084 RINOK(InStream_SeekSet(stream, _header.SectOffset))
969 size_t size = (size_t)_header.SectionEntrySize * _header.NumSections; 1085 const size_t size = (size_t)_header.SectionEntrySize * _header.NumSections;
970
971 CByteArr buf(size); 1086 CByteArr buf(size);
972
973 RINOK(ReadStream_FALSE(stream, buf, size)) 1087 RINOK(ReadStream_FALSE(stream, buf, size))
974 1088 {
975 UInt64 total = _header.SectOffset + size; 1089 const UInt64 total = _header.SectOffset + size;
976 if (_totalSize < total) 1090 if (_totalSize < total)
977 _totalSize = total; 1091 _totalSize = total;
978 1092 }
979 const Byte *p = buf;
980
981 if (addSections) 1093 if (addSections)
982 _sections.ClearAndReserve(_header.NumSections); 1094 _sections.ClearAndReserve(_header.NumSections);
1095 const Byte *p = buf;
983 for (unsigned i = 0; i < _header.NumSections; i++, p += _header.SectionEntrySize) 1096 for (unsigned i = 0; i < _header.NumSections; i++, p += _header.SectionEntrySize)
984 { 1097 {
985 CSection sect; 1098 CSection sect;
@@ -1000,18 +1113,17 @@ HRESULT CHandler::Open2(IInStream *stream)
1000 { 1113 {
1001 const CSection &sect = _sections[_header.NamesSectIndex]; 1114 const CSection &sect = _sections[_header.NamesSectIndex];
1002 const UInt64 size = sect.GetSize(); 1115 const UInt64 size = sect.GetSize();
1003 if (size != 0 1116 if (size && size < ((UInt64)1 << 31)
1004 && size < ((UInt64)1 << 31) 1117 && (Int64)sect.Offset >= 0)
1005 && (Int64)sect.Offset >= 0)
1006 { 1118 {
1007 _namesData.Alloc((size_t)size); 1119 _namesData.Alloc((size_t)size);
1008 RINOK(InStream_SeekSet(stream, sect.Offset)) 1120 RINOK(InStream_SeekSet(stream, sect.Offset))
1009 RINOK(ReadStream_FALSE(stream, _namesData, (size_t)size)) 1121 RINOK(ReadStream_FALSE(stream, _namesData, (size_t)size))
1010 } 1122 }
1011 } 1123 }
1012
1013 /* 1124 /*
1014 // we will not delete NULL sections, since we have links to section via indexes 1125 // we cannot delete "NULL" sections,
1126 // because we have links to sections array via indexes
1015 for (int i = _sections.Size() - 1; i >= 0; i--) 1127 for (int i = _sections.Size() - 1; i >= 0; i--)
1016 if (_sections[i].Type == SHT_NULL) 1128 if (_sections[i].Type == SHT_NULL)
1017 _items.Delete(i); 1129 _items.Delete(i);
@@ -1080,7 +1192,7 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
1080 } 1192 }
1081 RINOK(extractCallback->SetTotal(totalSize)) 1193 RINOK(extractCallback->SetTotal(totalSize))
1082 1194
1083 UInt64 currentTotalSize = 0; 1195 totalSize = 0;
1084 UInt64 currentItemSize; 1196 UInt64 currentItemSize;
1085 1197
1086 CMyComPtr2_Create<ICompressCoder, NCompress::CCopyCoder> copyCoder; 1198 CMyComPtr2_Create<ICompressCoder, NCompress::CCopyCoder> copyCoder;
@@ -1089,9 +1201,9 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
1089 CMyComPtr2_Create<ISequentialInStream, CLimitedSequentialInStream> inStream; 1201 CMyComPtr2_Create<ISequentialInStream, CLimitedSequentialInStream> inStream;
1090 inStream->SetStream(_inStream); 1202 inStream->SetStream(_inStream);
1091 1203
1092 for (i = 0;; i++, currentTotalSize += currentItemSize) 1204 for (i = 0;; i++, totalSize += currentItemSize)
1093 { 1205 {
1094 lps->InSize = lps->OutSize = currentTotalSize; 1206 lps->InSize = lps->OutSize = totalSize;
1095 RINOK(lps->SetCur()) 1207 RINOK(lps->SetCur())
1096 if (i >= numItems) 1208 if (i >= numItems)
1097 break; 1209 break;