diff options
Diffstat (limited to '')
-rw-r--r-- | CPP/7zip/Archive/ElfHandler.cpp | 318 |
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 | |||
20 | using namespace NWindows; | 22 | using namespace NWindows; |
21 | 23 | ||
22 | static UInt16 Get16(const Byte *p, bool be) { if (be) return GetBe16(p); return GetUi16(p); } | 24 | static UInt16 Get16(const Byte *p, bool be) { if (be) return GetBe16a(p); return GetUi16a(p); } |
23 | static UInt32 Get32(const Byte *p, bool be) { if (be) return GetBe32(p); return GetUi32(p); } | 25 | static UInt32 Get32(const Byte *p, bool be) { if (be) return GetBe32a(p); return GetUi32a(p); } |
24 | static UInt64 Get64(const Byte *p, bool be) { if (be) return GetBe64(p); return GetUi64(p); } | 26 | static 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 { | |||
31 | namespace NElf { | 33 | namespace NElf { |
32 | 34 | ||
33 | /* | 35 | /* |
34 | ELF Structure for most files (real order can be different): | 36 | ELF 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 | ||
50 | static const UInt32 kHeaderSize32 = 0x34; | 89 | static const unsigned kHeaderSize32 = 0x34; |
51 | static const UInt32 kHeaderSize64 = 0x40; | 90 | static const unsigned kHeaderSize64 = 0x40; |
52 | 91 | ||
53 | static const UInt32 kSegmentSize32 = 0x20; | 92 | static const unsigned kSegmentSize32 = 0x20; |
54 | static const UInt32 kSegmentSize64 = 0x38; | 93 | static const unsigned kSegmentSize64 = 0x38; |
55 | 94 | ||
56 | static const UInt32 kSectionSize32 = 0x28; | 95 | static const unsigned kSectionSize32 = 0x28; |
57 | static const UInt32 kSectionSize64 = 0x40; | 96 | static const unsigned kSectionSize64 = 0x40; |
58 | 97 | ||
59 | struct CHeader | 98 | struct 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 | ||
160 | static const CUInt32PCharPair g_SegnmentTypes[] = | 203 | static 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 | ||
293 | static const CUInt32PCharPair g_SectionFlags[] = | 344 | static 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[] = | |||
577 | static const CUInt32PCharPair g_MachinePairs[] = | 628 | static 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 | ||
584 | static const CUInt32PCharPair g_OS[] = | 635 | static 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: | |||
693 | void CHandler::GetSectionName(UInt32 index, NCOM::CPropVariant &prop, bool showNULL) const | 746 | void 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 §ion = _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 §ion = _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 | ||
715 | static const Byte kArcProps[] = | 772 | static const Byte kArcProps[] = |
@@ -726,7 +783,14 @@ static const Byte kArcProps[] = | |||
726 | enum | 783 | enum |
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 | ||
732 | static const CStatProp kProps[] = | 796 | static 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 | ||
912 | HRESULT CHandler::Open2(IInStream *stream) | 1021 | HRESULT 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 § = _sections[_header.NamesSectIndex]; | 1114 | const CSection § = _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; |