5
5
using System ;
6
6
using System . Collections . Generic ;
7
7
using System . IO ;
8
+ using static System . Collections . Specialized . BitVector32 ;
8
9
9
10
namespace LibObjectFile . Elf
10
11
{
@@ -17,8 +18,8 @@ internal abstract class ElfReader<TDecoder> : ElfReader where TDecoder : struct,
17
18
private TDecoder _decoder ;
18
19
private ulong _startOfFile ;
19
20
private ushort _programHeaderCount ;
20
- private ushort _sectionHeaderCount ;
21
- private ushort _sectionStringTableIndex ;
21
+ private uint _sectionHeaderCount ;
22
+ private uint _sectionStringTableIndex ;
22
23
private bool _isFirstSectionValidNull ;
23
24
private bool _hasValidSectionStringTable ;
24
25
@@ -193,7 +194,7 @@ private ElfSegment ReadProgramHeader64(int phdrIndex)
193
194
194
195
private void ReadSections ( )
195
196
{
196
- if ( _sectionHeaderCount == 0 ) return ;
197
+ if ( Layout . OffsetOfSectionHeaderTable == 0 ) return ;
197
198
198
199
// Write section header table
199
200
ReadSectionHeaderTable ( ) ;
@@ -210,9 +211,25 @@ private void ReadSectionHeaderTable()
210
211
return ;
211
212
}
212
213
213
- for ( int i = 0 ; i < _sectionHeaderCount ; i ++ )
214
+ uint i = 0 ;
215
+
216
+ if ( _sectionHeaderCount == 0 )
217
+ {
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 ++ )
214
231
{
215
- var offset = Layout . OffsetOfSectionHeaderTable + ( ulong ) i * Layout . SizeOfSectionHeaderEntry ;
232
+ var offset = Layout . OffsetOfSectionHeaderTable + i * Layout . SizeOfSectionHeaderEntry ;
216
233
217
234
if ( offset >= ( ulong ) Stream . Length )
218
235
{
@@ -228,12 +245,12 @@ private void ReadSectionHeaderTable()
228
245
}
229
246
}
230
247
231
- private ElfSection ReadSectionTableEntry ( int sectionIndex )
248
+ private ElfSection ReadSectionTableEntry ( uint sectionIndex )
232
249
{
233
250
return ObjectFile . FileClass == ElfFileClass . Is32 ? ReadSectionTableEntry32 ( sectionIndex ) : ReadSectionTableEntry64 ( sectionIndex ) ;
234
251
}
235
252
236
- private ElfSection ReadSectionTableEntry32 ( int sectionIndex )
253
+ private ElfSection ReadSectionTableEntry32 ( uint sectionIndex )
237
254
{
238
255
var streamOffset = Stream . Position ;
239
256
if ( ! TryReadData ( Layout . SizeOfSectionHeaderEntry , out ElfNative . Elf32_Shdr rawSection ) )
@@ -267,7 +284,7 @@ private ElfSection ReadSectionTableEntry32(int sectionIndex)
267
284
return section ;
268
285
}
269
286
270
- private ElfSection ReadSectionTableEntry64 ( int sectionIndex )
287
+ private ElfSection ReadSectionTableEntry64 ( uint sectionIndex )
271
288
{
272
289
var streamOffset = Stream . Position ;
273
290
if ( ! TryReadData ( Layout . SizeOfSectionHeaderEntry , out ElfNative . Elf64_Shdr rawSection ) )
@@ -300,13 +317,75 @@ private ElfSection ReadSectionTableEntry64(int sectionIndex)
300
317
301
318
return section ;
302
319
}
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
+ }
303
382
304
383
public override ElfSectionLink ResolveLink ( ElfSectionLink link , string errorMessageFormat )
305
384
{
306
385
if ( errorMessageFormat == null ) throw new ArgumentNullException ( nameof ( errorMessageFormat ) ) ;
307
386
308
387
// Connect section Link instance
309
- if ( ! link . IsSpecial )
388
+ if ( ! link . IsEmpty )
310
389
{
311
390
if ( link . SpecialIndex == _sectionStringTableIndex )
312
391
{
@@ -317,13 +396,21 @@ public override ElfSectionLink ResolveLink(ElfSectionLink link, string errorMess
317
396
var sectionIndex = link . SpecialIndex ;
318
397
319
398
bool sectionFound = false ;
320
- foreach ( var section in ObjectFile . Sections )
399
+ if ( sectionIndex < ObjectFile . Sections . Count && ObjectFile . Sections [ ( int ) sectionIndex ] . SectionIndex == sectionIndex )
321
400
{
322
- if ( section . SectionIndex == sectionIndex )
401
+ link = new ElfSectionLink ( ObjectFile . Sections [ ( int ) sectionIndex ] ) ;
402
+ sectionFound = true ;
403
+ }
404
+ else
405
+ {
406
+ foreach ( var section in ObjectFile . Sections )
323
407
{
324
- link = new ElfSectionLink ( section ) ;
325
- sectionFound = true ;
326
- break ;
408
+ if ( section . SectionIndex == sectionIndex )
409
+ {
410
+ link = new ElfSectionLink ( section ) ;
411
+ sectionFound = true ;
412
+ break ;
413
+ }
327
414
}
328
415
}
329
416
@@ -425,7 +512,7 @@ private void VerifyAndFixProgramHeadersAndSections()
425
512
// Make sure to pre-sort all sections by offset
426
513
var orderedSections = new List < ElfSection > ( ObjectFile . Sections . Count ) ;
427
514
orderedSections . AddRange ( ObjectFile . Sections ) ;
428
- orderedSections . Sort ( CompareSectionOffsetsDelegate ) ;
515
+ orderedSections . Sort ( CompareSectionOffsetsAndSizesDelegate ) ;
429
516
// Store the stream index to recover the same order when saving back.
430
517
for ( int i = 0 ; i < orderedSections . Count ; i ++ )
431
518
{
@@ -461,10 +548,10 @@ private void VerifyAndFixProgramHeadersAndSections()
461
548
lastOffset = section . Offset + section . Size - 1 ;
462
549
463
550
// Verify overlapping sections and generate and error
464
- for ( int j = i + 1 ; j < orderedSections . Count ; j ++ )
551
+ if ( i + 1 < orderedSections . Count )
465
552
{
466
- var otherSection = orderedSections [ j ] ;
467
- if ( section . Contains ( otherSection ) || otherSection . Contains ( section ) )
553
+ var otherSection = orderedSections [ i + 1 ] ;
554
+ if ( otherSection . Offset < section . Offset + section . Size )
468
555
{
469
556
Diagnostics . Warning ( DiagnosticId . ELF_ERR_InvalidOverlappingSections , $ "The section { section } [{ section . Offset } : { section . Offset + section . Size - 1 } ] is overlapping with the section { otherSection } [{ otherSection . Offset } : { otherSection . Offset + otherSection . Size - 1 } ]") ;
470
557
}
@@ -609,7 +696,7 @@ private void VerifyAndFixProgramHeadersAndSections()
609
696
}
610
697
}
611
698
612
- private ElfSection CreateElfSection ( int sectionIndex , ElfSectionType sectionType , bool isNullSection )
699
+ private ElfSection CreateElfSection ( uint sectionIndex , ElfSectionType sectionType , bool isNullSection )
613
700
{
614
701
ElfSection section = null ;
615
702
@@ -644,6 +731,9 @@ private ElfSection CreateElfSection(int sectionIndex, ElfSectionType sectionType
644
731
case ElfSectionType . Note :
645
732
section = new ElfNoteTable ( ) ;
646
733
break ;
734
+ case ElfSectionType . SymbolTableSectionHeaderIndices :
735
+ section = new ElfSymbolTableSectionHeaderIndices ( ) ;
736
+ break ;
647
737
}
648
738
649
739
// If the section is not a builtin section, try to offload to a delegate
@@ -754,11 +844,16 @@ public override ushort Decode(ElfNative.Elf64_Versym src)
754
844
return _decoder . Decode ( src ) ;
755
845
}
756
846
757
- private static readonly Comparison < ElfSection > CompareSectionOffsetsDelegate = new Comparison < ElfSection > ( CompareSectionOffsets ) ;
847
+ private static readonly Comparison < ElfSection > CompareSectionOffsetsAndSizesDelegate = new Comparison < ElfSection > ( CompareSectionOffsetsAndSizes ) ;
758
848
759
- private static int CompareSectionOffsets ( ElfSection left , ElfSection right )
849
+ private static int CompareSectionOffsetsAndSizes ( ElfSection left , ElfSection right )
760
850
{
761
- return left . Offset . CompareTo ( right . Offset ) ;
851
+ int result = left . Offset . CompareTo ( right . Offset ) ;
852
+ if ( result == 0 )
853
+ {
854
+ result = left . Size . CompareTo ( right . Size ) ;
855
+ }
856
+ return result ;
762
857
}
763
858
}
764
859
}
0 commit comments