@@ -27,6 +27,7 @@ import (
27
27
"io"
28
28
"os"
29
29
"strings"
30
+ "unsafe"
30
31
)
31
32
32
33
// TODO: error reporting detail
@@ -296,14 +297,16 @@ func NewFile(r io.ReaderAt) (*File, error) {
296
297
}
297
298
298
299
f .Data = Data (ident [EI_DATA ])
300
+ var bo binary.ByteOrder
299
301
switch f .Data {
300
302
case ELFDATA2LSB :
301
- f . ByteOrder = binary .LittleEndian
303
+ bo = binary .LittleEndian
302
304
case ELFDATA2MSB :
303
- f . ByteOrder = binary .BigEndian
305
+ bo = binary .BigEndian
304
306
default :
305
307
return nil , & FormatError {0 , "unknown ELF data encoding" , f .Data }
306
308
}
309
+ f .ByteOrder = bo
307
310
308
311
f .Version = Version (ident [EI_VERSION ])
309
312
if f .Version != EV_CURRENT {
@@ -320,43 +323,43 @@ func NewFile(r io.ReaderAt) (*File, error) {
320
323
var shentsize , shnum , shstrndx int
321
324
switch f .Class {
322
325
case ELFCLASS32 :
323
- hdr := new ( Header32 )
324
- sr . Seek ( 0 , io . SeekStart )
325
- if err := binary . Read ( sr , f . ByteOrder , hdr ); err != nil {
326
+ var hdr Header32
327
+ data := make ([] byte , unsafe . Sizeof ( hdr ) )
328
+ if _ , err := sr . ReadAt ( data , 0 ); err != nil {
326
329
return nil , err
327
330
}
328
- f .Type = Type (hdr .Type )
329
- f .Machine = Machine (hdr .Machine )
330
- f .Entry = uint64 (hdr .Entry )
331
- if v := Version (hdr .Version ); v != f .Version {
331
+ f .Type = Type (bo . Uint16 ( data [ unsafe . Offsetof ( hdr .Type ):]) )
332
+ f .Machine = Machine (bo . Uint16 ( data [ unsafe . Offsetof ( hdr .Machine ):]) )
333
+ f .Entry = uint64 (bo . Uint32 ( data [ unsafe . Offsetof ( hdr .Entry ):]) )
334
+ if v := Version (bo . Uint32 ( data [ unsafe . Offsetof ( hdr .Version ):]) ); v != f .Version {
332
335
return nil , & FormatError {0 , "mismatched ELF version" , v }
333
336
}
334
- phoff = int64 (hdr .Phoff )
335
- phentsize = int (hdr .Phentsize )
336
- phnum = int (hdr .Phnum )
337
- shoff = int64 (hdr .Shoff )
338
- shentsize = int (hdr .Shentsize )
339
- shnum = int (hdr .Shnum )
340
- shstrndx = int (hdr .Shstrndx )
337
+ phoff = int64 (bo . Uint32 ( data [ unsafe . Offsetof ( hdr .Phoff ):]) )
338
+ phentsize = int (bo . Uint16 ( data [ unsafe . Offsetof ( hdr .Phentsize ):]) )
339
+ phnum = int (bo . Uint16 ( data [ unsafe . Offsetof ( hdr .Phnum ):]) )
340
+ shoff = int64 (bo . Uint32 ( data [ unsafe . Offsetof ( hdr .Shoff ):]) )
341
+ shentsize = int (bo . Uint16 ( data [ unsafe . Offsetof ( hdr .Shentsize ):]) )
342
+ shnum = int (bo . Uint16 ( data [ unsafe . Offsetof ( hdr .Shnum ):]) )
343
+ shstrndx = int (bo . Uint16 ( data [ unsafe . Offsetof ( hdr .Shstrndx ):]) )
341
344
case ELFCLASS64 :
342
- hdr := new ( Header64 )
343
- sr . Seek ( 0 , io . SeekStart )
344
- if err := binary . Read ( sr , f . ByteOrder , hdr ); err != nil {
345
+ var hdr Header64
346
+ data := make ([] byte , unsafe . Sizeof ( hdr ) )
347
+ if _ , err := sr . ReadAt ( data , 0 ); err != nil {
345
348
return nil , err
346
349
}
347
- f .Type = Type (hdr .Type )
348
- f .Machine = Machine (hdr .Machine )
349
- f .Entry = hdr .Entry
350
- if v := Version (hdr .Version ); v != f .Version {
350
+ f .Type = Type (bo . Uint16 ( data [ unsafe . Offsetof ( hdr .Type ):]) )
351
+ f .Machine = Machine (bo . Uint16 ( data [ unsafe . Offsetof ( hdr .Machine ):]) )
352
+ f .Entry = bo . Uint64 ( data [ unsafe . Offsetof ( hdr .Entry ):])
353
+ if v := Version (bo . Uint32 ( data [ unsafe . Offsetof ( hdr .Version ):]) ); v != f .Version {
351
354
return nil , & FormatError {0 , "mismatched ELF version" , v }
352
355
}
353
- phoff = int64 (hdr .Phoff )
354
- phentsize = int (hdr .Phentsize )
355
- phnum = int (hdr .Phnum )
356
- shoff = int64 (hdr .Shoff )
357
- shentsize = int (hdr .Shentsize )
358
- shnum = int (hdr .Shnum )
359
- shstrndx = int (hdr .Shstrndx )
356
+ phoff = int64 (bo . Uint64 ( data [ unsafe . Offsetof ( hdr .Phoff ):]) )
357
+ phentsize = int (bo . Uint16 ( data [ unsafe . Offsetof ( hdr .Phentsize ):]) )
358
+ phnum = int (bo . Uint16 ( data [ unsafe . Offsetof ( hdr .Phnum ):]) )
359
+ shoff = int64 (bo . Uint64 ( data [ unsafe . Offsetof ( hdr .Shoff ):]) )
360
+ shentsize = int (bo . Uint16 ( data [ unsafe . Offsetof ( hdr .Shentsize ):]) )
361
+ shnum = int (bo . Uint16 ( data [ unsafe . Offsetof ( hdr .Shnum ):]) )
362
+ shstrndx = int (bo . Uint16 ( data [ unsafe . Offsetof ( hdr .Shstrndx ):]) )
360
363
}
361
364
362
365
if shoff < 0 {
@@ -389,47 +392,44 @@ func NewFile(r io.ReaderAt) (*File, error) {
389
392
390
393
// Read program headers
391
394
f .Progs = make ([]* Prog , phnum )
395
+ phdata , err := saferio .ReadDataAt (sr , uint64 (phnum )* uint64 (phentsize ), phoff )
396
+ if err != nil {
397
+ return nil , err
398
+ }
392
399
for i := 0 ; i < phnum ; i ++ {
393
- off := phoff + int64 (i )* int64 (phentsize )
394
- sr .Seek (off , io .SeekStart )
400
+ off := uintptr (i ) * uintptr (phentsize )
395
401
p := new (Prog )
396
402
switch f .Class {
397
403
case ELFCLASS32 :
398
- ph := new (Prog32 )
399
- if err := binary .Read (sr , f .ByteOrder , ph ); err != nil {
400
- return nil , err
401
- }
404
+ var ph Prog32
402
405
p .ProgHeader = ProgHeader {
403
- Type : ProgType (ph .Type ),
404
- Flags : ProgFlag (ph .Flags ),
405
- Off : uint64 (ph .Off ),
406
- Vaddr : uint64 (ph .Vaddr ),
407
- Paddr : uint64 (ph .Paddr ),
408
- Filesz : uint64 (ph .Filesz ),
409
- Memsz : uint64 (ph .Memsz ),
410
- Align : uint64 (ph .Align ),
406
+ Type : ProgType (bo . Uint32 ( phdata [ off + unsafe . Offsetof ( ph .Type ):]) ),
407
+ Flags : ProgFlag (bo . Uint32 ( phdata [ off + unsafe . Offsetof ( ph .Flags ):]) ),
408
+ Off : uint64 (bo . Uint32 ( phdata [ off + unsafe . Offsetof ( ph .Off ):]) ),
409
+ Vaddr : uint64 (bo . Uint32 ( phdata [ off + unsafe . Offsetof ( ph .Vaddr ):]) ),
410
+ Paddr : uint64 (bo . Uint32 ( phdata [ off + unsafe . Offsetof ( ph .Paddr ):]) ),
411
+ Filesz : uint64 (bo . Uint32 ( phdata [ off + unsafe . Offsetof ( ph .Filesz ):]) ),
412
+ Memsz : uint64 (bo . Uint32 ( phdata [ off + unsafe . Offsetof ( ph .Memsz ):]) ),
413
+ Align : uint64 (bo . Uint32 ( phdata [ off + unsafe . Offsetof ( ph .Align ):]) ),
411
414
}
412
415
case ELFCLASS64 :
413
- ph := new (Prog64 )
414
- if err := binary .Read (sr , f .ByteOrder , ph ); err != nil {
415
- return nil , err
416
- }
416
+ var ph Prog64
417
417
p .ProgHeader = ProgHeader {
418
- Type : ProgType (ph .Type ),
419
- Flags : ProgFlag (ph .Flags ),
420
- Off : ph .Off ,
421
- Vaddr : ph .Vaddr ,
422
- Paddr : ph .Paddr ,
423
- Filesz : ph .Filesz ,
424
- Memsz : ph .Memsz ,
425
- Align : ph .Align ,
418
+ Type : ProgType (bo . Uint32 ( phdata [ off + unsafe . Offsetof ( ph .Type ):]) ),
419
+ Flags : ProgFlag (bo . Uint32 ( phdata [ off + unsafe . Offsetof ( ph .Flags ):]) ),
420
+ Off : bo . Uint64 ( phdata [ off + unsafe . Offsetof ( ph .Off ):]) ,
421
+ Vaddr : bo . Uint64 ( phdata [ off + unsafe . Offsetof ( ph .Vaddr ):]) ,
422
+ Paddr : bo . Uint64 ( phdata [ off + unsafe . Offsetof ( ph .Paddr ):]) ,
423
+ Filesz : bo . Uint64 ( phdata [ off + unsafe . Offsetof ( ph .Filesz ):]) ,
424
+ Memsz : bo . Uint64 ( phdata [ off + unsafe . Offsetof ( ph .Memsz ):]) ,
425
+ Align : bo . Uint64 ( phdata [ off + unsafe . Offsetof ( ph .Align ):]) ,
426
426
}
427
427
}
428
428
if int64 (p .Off ) < 0 {
429
- return nil , & FormatError {off , "invalid program header offset" , p .Off }
429
+ return nil , & FormatError {phoff + int64 ( off ) , "invalid program header offset" , p .Off }
430
430
}
431
431
if int64 (p .Filesz ) < 0 {
432
- return nil , & FormatError {off , "invalid program header file size" , p .Filesz }
432
+ return nil , & FormatError {phoff + int64 ( off ) , "invalid program header file size" , p .Filesz }
433
433
}
434
434
p .sr = io .NewSectionReader (r , int64 (p .Off ), int64 (p .Filesz ))
435
435
p .ReaderAt = p .sr
@@ -446,15 +446,15 @@ func NewFile(r io.ReaderAt) (*File, error) {
446
446
switch f .Class {
447
447
case ELFCLASS32 :
448
448
sh := new (Section32 )
449
- if err := binary .Read (sr , f . ByteOrder , sh ); err != nil {
449
+ if err := binary .Read (sr , bo , sh ); err != nil {
450
450
return nil , err
451
451
}
452
452
shnum = int (sh .Size )
453
453
typ = sh .Type
454
454
link = sh .Link
455
455
case ELFCLASS64 :
456
456
sh := new (Section64 )
457
- if err := binary .Read (sr , f . ByteOrder , sh ); err != nil {
457
+ if err := binary .Read (sr , bo , sh ); err != nil {
458
458
return nil , err
459
459
}
460
460
shnum = int (sh .Size )
@@ -493,51 +493,48 @@ func NewFile(r io.ReaderAt) (*File, error) {
493
493
}
494
494
f .Sections = make ([]* Section , 0 , c )
495
495
names := make ([]uint32 , 0 , c )
496
+ shdata , err := saferio .ReadDataAt (sr , uint64 (shnum )* uint64 (shentsize ), shoff )
497
+ if err != nil {
498
+ return nil , err
499
+ }
496
500
for i := 0 ; i < shnum ; i ++ {
497
- off := shoff + int64 (i )* int64 (shentsize )
498
- sr .Seek (off , io .SeekStart )
501
+ off := uintptr (i ) * uintptr (shentsize )
499
502
s := new (Section )
500
503
switch f .Class {
501
504
case ELFCLASS32 :
502
- sh := new (Section32 )
503
- if err := binary .Read (sr , f .ByteOrder , sh ); err != nil {
504
- return nil , err
505
- }
506
- names = append (names , sh .Name )
505
+ var sh Section32
506
+ names = append (names , bo .Uint32 (shdata [off + unsafe .Offsetof (sh .Name ):]))
507
507
s .SectionHeader = SectionHeader {
508
- Type : SectionType (sh .Type ),
509
- Flags : SectionFlag (sh .Flags ),
510
- Addr : uint64 (sh .Addr ),
511
- Offset : uint64 (sh .Off ),
512
- FileSize : uint64 (sh .Size ),
513
- Link : sh .Link ,
514
- Info : sh .Info ,
515
- Addralign : uint64 (sh .Addralign ),
516
- Entsize : uint64 (sh .Entsize ),
508
+ Type : SectionType (bo . Uint32 ( shdata [ off + unsafe . Offsetof ( sh .Type ):]) ),
509
+ Flags : SectionFlag (bo . Uint32 ( shdata [ off + unsafe . Offsetof ( sh .Flags ):]) ),
510
+ Addr : uint64 (bo . Uint32 ( shdata [ off + unsafe . Offsetof ( sh .Addr ):]) ),
511
+ Offset : uint64 (bo . Uint32 ( shdata [ off + unsafe . Offsetof ( sh .Off ):]) ),
512
+ FileSize : uint64 (bo . Uint32 ( shdata [ off + unsafe . Offsetof ( sh .Size ):]) ),
513
+ Link : bo . Uint32 ( shdata [ off + unsafe . Offsetof ( sh .Link ):]) ,
514
+ Info : bo . Uint32 ( shdata [ off + unsafe . Offsetof ( sh .Info ):]) ,
515
+ Addralign : uint64 (bo . Uint32 ( shdata [ off + unsafe . Offsetof ( sh .Addralign ):]) ),
516
+ Entsize : uint64 (bo . Uint32 ( shdata [ off + unsafe . Offsetof ( sh .Entsize ):]) ),
517
517
}
518
518
case ELFCLASS64 :
519
- sh := new (Section64 )
520
- if err := binary .Read (sr , f .ByteOrder , sh ); err != nil {
521
- return nil , err
522
- }
523
- names = append (names , sh .Name )
519
+ var sh Section64
520
+ names = append (names , bo .Uint32 (shdata [off + unsafe .Offsetof (sh .Name ):]))
524
521
s .SectionHeader = SectionHeader {
525
- Type : SectionType (sh .Type ),
526
- Flags : SectionFlag (sh .Flags ),
527
- Offset : sh .Off ,
528
- FileSize : sh .Size ,
529
- Addr : sh .Addr ,
530
- Link : sh .Link ,
531
- Info : sh .Info ,
532
- Addralign : sh .Addralign ,
533
- Entsize : sh .Entsize ,
522
+ Type : SectionType (bo . Uint32 ( shdata [ off + unsafe . Offsetof ( sh .Type ):]) ),
523
+ Flags : SectionFlag (bo . Uint64 ( shdata [ off + unsafe . Offsetof ( sh .Flags ):]) ),
524
+ Offset : bo . Uint64 ( shdata [ off + unsafe . Offsetof ( sh .Off ):]) ,
525
+ FileSize : bo . Uint64 ( shdata [ off + unsafe . Offsetof ( sh .Size ):]) ,
526
+ Addr : bo . Uint64 ( shdata [ off + unsafe . Offsetof ( sh .Addr ):]) ,
527
+ Link : bo . Uint32 ( shdata [ off + unsafe . Offsetof ( sh .Link ):]) ,
528
+ Info : bo . Uint32 ( shdata [ off + unsafe . Offsetof ( sh .Info ):]) ,
529
+ Addralign : bo . Uint64 ( shdata [ off + unsafe . Offsetof ( sh .Addralign ):]) ,
530
+ Entsize : bo . Uint64 ( shdata [ off + unsafe . Offsetof ( sh .Entsize ):]) ,
534
531
}
535
532
}
536
533
if int64 (s .Offset ) < 0 {
537
- return nil , & FormatError {off , "invalid section offset" , int64 (s .Offset )}
534
+ return nil , & FormatError {shoff + int64 ( off ) , "invalid section offset" , int64 (s .Offset )}
538
535
}
539
536
if int64 (s .FileSize ) < 0 {
540
- return nil , & FormatError {off , "invalid section size" , int64 (s .FileSize )}
537
+ return nil , & FormatError {shoff + int64 ( off ) , "invalid section size" , int64 (s .FileSize )}
541
538
}
542
539
s .sr = io .NewSectionReader (r , int64 (s .Offset ), int64 (s .FileSize ))
543
540
@@ -548,23 +545,25 @@ func NewFile(r io.ReaderAt) (*File, error) {
548
545
// Read the compression header.
549
546
switch f .Class {
550
547
case ELFCLASS32 :
551
- ch := new (Chdr32 )
552
- if err := binary .Read (s .sr , f .ByteOrder , ch ); err != nil {
548
+ var ch Chdr32
549
+ chdata := make ([]byte , unsafe .Sizeof (ch ))
550
+ if _ , err := s .sr .ReadAt (chdata , 0 ); err != nil {
553
551
return nil , err
554
552
}
555
- s .compressionType = CompressionType (ch .Type )
556
- s .Size = uint64 (ch .Size )
557
- s .Addralign = uint64 (ch .Addralign )
558
- s .compressionOffset = int64 (binary . Size (ch ))
553
+ s .compressionType = CompressionType (bo . Uint32 ( chdata [ unsafe . Offsetof ( ch .Type ):]) )
554
+ s .Size = uint64 (bo . Uint32 ( chdata [ unsafe . Offsetof ( ch .Size ):]) )
555
+ s .Addralign = uint64 (bo . Uint32 ( chdata [ unsafe . Offsetof ( ch .Addralign ):]) )
556
+ s .compressionOffset = int64 (unsafe . Sizeof (ch ))
559
557
case ELFCLASS64 :
560
- ch := new (Chdr64 )
561
- if err := binary .Read (s .sr , f .ByteOrder , ch ); err != nil {
558
+ var ch Chdr64
559
+ chdata := make ([]byte , unsafe .Sizeof (ch ))
560
+ if _ , err := s .sr .ReadAt (chdata , 0 ); err != nil {
562
561
return nil , err
563
562
}
564
- s .compressionType = CompressionType (ch .Type )
565
- s .Size = ch .Size
566
- s .Addralign = ch .Addralign
567
- s .compressionOffset = int64 (binary . Size (ch ))
563
+ s .compressionType = CompressionType (bo . Uint32 ( chdata [ unsafe . Offsetof ( ch .Type ):]) )
564
+ s .Size = bo . Uint64 ( chdata [ unsafe . Offsetof ( ch .Size ):])
565
+ s .Addralign = bo . Uint64 ( chdata [ unsafe . Offsetof ( ch .Addralign ):])
566
+ s .compressionOffset = int64 (unsafe . Sizeof (ch ))
568
567
}
569
568
}
570
569
0 commit comments