55using System ;
66using System . Collections . Generic ;
77using System . IO ;
8+ using static System . Collections . Specialized . BitVector32 ;
89
910namespace LibObjectFile . Elf
1011{
@@ -17,8 +18,8 @@ internal abstract class ElfReader<TDecoder> : ElfReader where TDecoder : struct,
1718 private TDecoder _decoder ;
1819 private ulong _startOfFile ;
1920 private ushort _programHeaderCount ;
20- private ushort _sectionHeaderCount ;
21- private ushort _sectionStringTableIndex ;
21+ private uint _sectionHeaderCount ;
22+ private uint _sectionStringTableIndex ;
2223 private bool _isFirstSectionValidNull ;
2324 private bool _hasValidSectionStringTable ;
2425
@@ -193,7 +194,7 @@ private ElfSegment ReadProgramHeader64(int phdrIndex)
193194
194195 private void ReadSections ( )
195196 {
196- if ( _sectionHeaderCount == 0 ) return ;
197+ if ( Layout . OffsetOfSectionHeaderTable == 0 ) return ;
197198
198199 // Write section header table
199200 ReadSectionHeaderTable ( ) ;
@@ -210,9 +211,25 @@ private void ReadSectionHeaderTable()
210211 return ;
211212 }
212213
213- for ( int i = 0 ; i < _sectionHeaderCount ; i ++ )
214+ uint i = 0 ;
215+
216+ if ( _sectionHeaderCount == 0 )
214217 {
215- var offset = Layout . OffsetOfSectionHeaderTable + ( ulong ) i * Layout . SizeOfSectionHeaderEntry ;
218+ // We are dealing with an object file that has more than SHN_LORESERVE
219+ // (0xff00) sections. It has to begin with a NULL section header where
220+ // its Size contains the real number of sections, and Link optionally
221+ // points to string table section if it's section index is too high.
222+ if ( ReadExtendedNullSectionTableEntry ( ) )
223+ {
224+ i = 1 ;
225+ ObjectFile . AddSection ( new ElfNullSection ( ) ) ;
226+ _isFirstSectionValidNull = true ;
227+ }
228+ }
229+
230+ for ( ; i < _sectionHeaderCount ; i ++ )
231+ {
232+ var offset = Layout . OffsetOfSectionHeaderTable + i * Layout . SizeOfSectionHeaderEntry ;
216233
217234 if ( offset >= ( ulong ) Stream . Length )
218235 {
@@ -228,12 +245,12 @@ private void ReadSectionHeaderTable()
228245 }
229246 }
230247
231- private ElfSection ReadSectionTableEntry ( int sectionIndex )
248+ private ElfSection ReadSectionTableEntry ( uint sectionIndex )
232249 {
233250 return ObjectFile . FileClass == ElfFileClass . Is32 ? ReadSectionTableEntry32 ( sectionIndex ) : ReadSectionTableEntry64 ( sectionIndex ) ;
234251 }
235252
236- private ElfSection ReadSectionTableEntry32 ( int sectionIndex )
253+ private ElfSection ReadSectionTableEntry32 ( uint sectionIndex )
237254 {
238255 var streamOffset = Stream . Position ;
239256 if ( ! TryReadData ( Layout . SizeOfSectionHeaderEntry , out ElfNative . Elf32_Shdr rawSection ) )
@@ -267,7 +284,7 @@ private ElfSection ReadSectionTableEntry32(int sectionIndex)
267284 return section ;
268285 }
269286
270- private ElfSection ReadSectionTableEntry64 ( int sectionIndex )
287+ private ElfSection ReadSectionTableEntry64 ( uint sectionIndex )
271288 {
272289 var streamOffset = Stream . Position ;
273290 if ( ! TryReadData ( Layout . SizeOfSectionHeaderEntry , out ElfNative . Elf64_Shdr rawSection ) )
@@ -300,6 +317,68 @@ private ElfSection ReadSectionTableEntry64(int sectionIndex)
300317
301318 return section ;
302319 }
320+
321+ private bool ReadExtendedNullSectionTableEntry ( )
322+ {
323+ uint sh_type ;
324+ ulong sh_size ;
325+ uint sh_link ;
326+ bool isNull ;
327+
328+ Stream . Position = ( long ) Layout . OffsetOfSectionHeaderTable ;
329+
330+ if ( ObjectFile . FileClass == ElfFileClass . Is32 )
331+ {
332+
333+ if ( ! TryReadData ( Layout . SizeOfSectionHeaderEntry , out ElfNative . Elf32_Shdr rawSection32 ) )
334+ {
335+ Diagnostics . Error ( DiagnosticId . ELF_ERR_IncompleteSectionHeader32Size , $ "Unable to read entirely NULL section header. Not enough data (size: { Layout . SizeOfSectionHeaderEntry } ) read at offset { Layout . OffsetOfSectionHeaderTable } from the stream") ;
336+ return false ;
337+ }
338+
339+ sh_type = _decoder . Decode ( rawSection32 . sh_type ) ;
340+ sh_size = _decoder . Decode ( rawSection32 . sh_size ) ;
341+ sh_link = _decoder . Decode ( rawSection32 . sh_link ) ;
342+ rawSection32 . sh_size = 0 ;
343+ rawSection32 . sh_link = 0 ;
344+ isNull = rawSection32 . IsNull ;
345+ }
346+ else
347+ {
348+ if ( ! TryReadData ( Layout . SizeOfSectionHeaderEntry , out ElfNative . Elf64_Shdr rawSection64 ) )
349+ {
350+ Diagnostics . Error ( DiagnosticId . ELF_ERR_IncompleteSectionHeader64Size , $ "Unable to read entirely NULL section header. Not enough data (size: { Layout . SizeOfSectionHeaderEntry } ) read at offset { Layout . OffsetOfSectionHeaderTable } from the stream") ;
351+ return false ;
352+ }
353+
354+ sh_type = _decoder . Decode ( rawSection64 . sh_type ) ;
355+ sh_size = _decoder . Decode ( rawSection64 . sh_size ) ;
356+ sh_link = _decoder . Decode ( rawSection64 . sh_link ) ;
357+ rawSection64 . sh_size = 0 ;
358+ rawSection64 . sh_link = 0 ;
359+ isNull = rawSection64 . IsNull ;
360+ }
361+
362+ if ( ! isNull )
363+ {
364+ Diagnostics . Error ( DiagnosticId . ELF_ERR_InvalidFirstSectionExpectingUndefined , $ "Invalid Section [0] { ( ElfSectionType ) sh_type } . Expecting { ElfNative . SHN_UNDEF } ") ;
365+ return false ;
366+ }
367+
368+ if ( sh_size >= uint . MaxValue )
369+ {
370+ Diagnostics . Error ( DiagnosticId . ELF_ERR_InvalidSectionHeaderCount , $ "Extended section count [{ sh_size } ] exceeds { uint . MaxValue } ") ;
371+ return false ;
372+ }
373+
374+ _sectionHeaderCount = ( uint ) sh_size ;
375+ if ( _sectionStringTableIndex == ElfNative . SHN_XINDEX )
376+ {
377+ _sectionStringTableIndex = sh_link ;
378+ }
379+
380+ return true ;
381+ }
303382
304383 public override ElfSectionLink ResolveLink ( ElfSectionLink link , string errorMessageFormat )
305384 {
@@ -609,7 +688,7 @@ private void VerifyAndFixProgramHeadersAndSections()
609688 }
610689 }
611690
612- private ElfSection CreateElfSection ( int sectionIndex , ElfSectionType sectionType , bool isNullSection )
691+ private ElfSection CreateElfSection ( uint sectionIndex , ElfSectionType sectionType , bool isNullSection )
613692 {
614693 ElfSection section = null ;
615694
0 commit comments