"compress/gzip"
"debug/dwarf"
"encoding/binary"
+ "fmt"
"io"
"math/rand"
"net"
continue
}
defer f.Close()
- if !reflect.DeepEqual(f.FileHeader, tt.hdr) {
+ if f.FileHeader != tt.hdr {
t.Errorf("open %s:\n\thave %#v\n\twant %#v\n", tt.file, f.FileHeader, tt.hdr)
continue
}
if i >= len(tt.sections) {
break
}
- sh := &tt.sections[i]
- if !reflect.DeepEqual(&s.SectionHeader, sh) {
- t.Errorf("open %s, section %d:\n\thave %#v\n\twant %#v\n", tt.file, i, &s.SectionHeader, sh)
+ sh := tt.sections[i]
+ if s.SectionHeader != sh {
+ t.Errorf("open %s, section %d:\n\thave %#v\n\twant %#v\n", tt.file, i, s.SectionHeader, sh)
}
}
for i, p := range f.Progs {
if i >= len(tt.progs) {
break
}
- ph := &tt.progs[i]
- if !reflect.DeepEqual(&p.ProgHeader, ph) {
- t.Errorf("open %s, program %d:\n\thave %#v\n\twant %#v\n", tt.file, i, &p.ProgHeader, ph)
+ ph := tt.progs[i]
+ if p.ProgHeader != ph {
+ t.Errorf("open %s, program %d:\n\thave %#v\n\twant %#v\n", tt.file, i, p.ProgHeader, ph)
}
}
tn := len(tt.sections)
}
}
+// TestLargeNumberOfSections tests the case that a file has greater than or
+// equal to 65280 (0xff00) sections.
+func TestLargeNumberOfSections(t *testing.T) {
+ // A file with >= 0xff00 sections is too big, so we will construct it on the
+ // fly. The original file "y.o" is generated by these commands:
+ // 1. generate "y.c":
+ // for i in `seq 1 65288`; do
+ // printf -v x "%04x" i;
+ // echo "int var_$x __attribute__((section(\"section_$x\"))) = $i;"
+ // done > y.c
+ // 2. compile: gcc -c y.c -m32
+ //
+ // $readelf -h y.o
+ // ELF Header:
+ // Magic: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
+ // Class: ELF32
+ // Data: 2's complement, little endian
+ // Version: 1 (current)
+ // OS/ABI: UNIX - System V
+ // ABI Version: 0
+ // Type: REL (Relocatable file)
+ // Machine: Intel 80386
+ // Version: 0x1
+ // Entry point address: 0x0
+ // Start of program headers: 0 (bytes into file)
+ // Start of section headers: 3003468 (bytes into file)
+ // Flags: 0x0
+ // Size of this header: 52 (bytes)
+ // Size of program headers: 0 (bytes)
+ // Number of program headers: 0
+ // Size of section headers: 40 (bytes)
+ // Number of section headers: 0 (65298)
+ // Section header string table index: 65535 (65297)
+ //
+ // $readelf -S y.o
+ // There are 65298 section headers, starting at offset 0x2dd44c:
+ // Section Headers:
+ // [Nr] Name Type Addr Off Size ES Flg Lk Inf Al
+ // [ 0] NULL 00000000 000000 00ff12 00 65297 0 0
+ // [ 1] .text PROGBITS 00000000 000034 000000 00 AX 0 0 1
+ // [ 2] .data PROGBITS 00000000 000034 000000 00 WA 0 0 1
+ // [ 3] .bss NOBITS 00000000 000034 000000 00 WA 0 0 1
+ // [ 4] section_0001 PROGBITS 00000000 000034 000004 00 WA 0 0 4
+ // [ 5] section_0002 PROGBITS 00000000 000038 000004 00 WA 0 0 4
+ // [ section_0003 ~ section_ff06 truncated ]
+ // [65290] section_ff07 PROGBITS 00000000 03fc4c 000004 00 WA 0 0 4
+ // [65291] section_ff08 PROGBITS 00000000 03fc50 000004 00 WA 0 0 4
+ // [65292] .comment PROGBITS 00000000 03fc54 000027 01 MS 0 0 1
+ // [65293] .note.GNU-stack PROGBITS 00000000 03fc7b 000000 00 0 0 1
+ // [65294] .symtab SYMTAB 00000000 03fc7c 0ff0a0 10 65296 2 4
+ // [65295] .symtab_shndx SYMTAB SECTION 00000000 13ed1c 03fc28 04 65294 0 4
+ // [65296] .strtab STRTAB 00000000 17e944 08f74d 00 0 0 1
+ // [65297] .shstrtab STRTAB 00000000 20e091 0cf3bb 00 0 0 1
+
+ var buf bytes.Buffer
+
+ {
+ buf.Grow(0x55AF1C) // 3003468 + 40 * 65298
+
+ h := Header32{
+ Ident: [16]byte{0x7F, 'E', 'L', 'F', 0x01, 0x01, 0x01},
+ Type: 1,
+ Machine: 3,
+ Version: 1,
+ Shoff: 0x2DD44C,
+ Ehsize: 0x34,
+ Shentsize: 0x28,
+ Shnum: 0,
+ Shstrndx: 0xFFFF,
+ }
+ binary.Write(&buf, binary.LittleEndian, h)
+
+ // Zero out sections [1]~[65294].
+ buf.Write(bytes.Repeat([]byte{0}, 0x13ED1C-binary.Size(h)))
+
+ // Write section [65295]. Section [65295] are all zeros except for the
+ // last 48 bytes.
+ buf.Write(bytes.Repeat([]byte{0}, 0x03FC28-12*4))
+ for i := 0; i < 12; i++ {
+ binary.Write(&buf, binary.LittleEndian, uint32(0xFF00|i))
+ }
+
+ // Write section [65296].
+ buf.Write([]byte{0})
+ buf.Write([]byte("y.c\x00"))
+ for i := 1; i <= 65288; i++ {
+ // var_0001 ~ var_ff08
+ name := fmt.Sprintf("var_%04x", i)
+ buf.Write([]byte(name))
+ buf.Write([]byte{0})
+ }
+
+ // Write section [65297].
+ buf.Write([]byte{0})
+ buf.Write([]byte(".symtab\x00"))
+ buf.Write([]byte(".strtab\x00"))
+ buf.Write([]byte(".shstrtab\x00"))
+ buf.Write([]byte(".text\x00"))
+ buf.Write([]byte(".data\x00"))
+ buf.Write([]byte(".bss\x00"))
+ for i := 1; i <= 65288; i++ {
+ // s_0001 ~ s_ff08
+ name := fmt.Sprintf("section_%04x", i)
+ buf.Write([]byte(name))
+ buf.Write([]byte{0})
+ }
+ buf.Write([]byte(".comment\x00"))
+ buf.Write([]byte(".note.GNU-stack\x00"))
+ buf.Write([]byte(".symtab_shndx\x00"))
+
+ // Write section header table.
+ // NULL
+ binary.Write(&buf, binary.LittleEndian, Section32{Name: 0, Size: 0xFF12, Link: 0xFF11})
+ // .text
+ binary.Write(&buf, binary.LittleEndian, Section32{
+ Name: 0x1B,
+ Type: uint32(SHT_PROGBITS),
+ Flags: uint32(uint32(SHF_ALLOC | SHF_EXECINSTR)),
+ Off: 0x34,
+ Addralign: 0x01,
+ })
+ // .data
+ binary.Write(&buf, binary.LittleEndian, Section32{
+ Name: 0x21,
+ Type: uint32(SHT_PROGBITS),
+ Flags: uint32(SHF_WRITE | SHF_ALLOC),
+ Off: 0x34,
+ Addralign: 0x01,
+ })
+ // .bss
+ binary.Write(&buf, binary.LittleEndian, Section32{
+ Name: 0x27,
+ Type: uint32(SHT_NOBITS),
+ Flags: uint32(SHF_WRITE | SHF_ALLOC),
+ Off: 0x34,
+ Addralign: 0x01,
+ })
+ // s_1 ~ s_65537
+ for i := 0; i < 65288; i++ {
+ s := Section32{
+ Name: uint32(0x2C + i*13),
+ Type: uint32(SHT_PROGBITS),
+ Flags: uint32(SHF_WRITE | SHF_ALLOC),
+ Off: uint32(0x34 + i*4),
+ Size: 0x04,
+ Addralign: 0x04,
+ }
+ binary.Write(&buf, binary.LittleEndian, s)
+ }
+ // .comment
+ binary.Write(&buf, binary.LittleEndian, Section32{
+ Name: 0x0CF394,
+ Type: uint32(SHT_PROGBITS),
+ Flags: uint32(SHF_MERGE | SHF_STRINGS),
+ Off: 0x03FC54,
+ Size: 0x27,
+ Addralign: 0x01,
+ Entsize: 0x01,
+ })
+ // .note.GNU-stack
+ binary.Write(&buf, binary.LittleEndian, Section32{
+ Name: 0x0CF39D,
+ Type: uint32(SHT_PROGBITS),
+ Off: 0x03FC7B,
+ Addralign: 0x01,
+ })
+ // .symtab
+ binary.Write(&buf, binary.LittleEndian, Section32{
+ Name: 0x01,
+ Type: uint32(SHT_SYMTAB),
+ Off: 0x03FC7C,
+ Size: 0x0FF0A0,
+ Link: 0xFF10,
+ Info: 0x02,
+ Addralign: 0x04,
+ Entsize: 0x10,
+ })
+ // .symtab_shndx
+ binary.Write(&buf, binary.LittleEndian, Section32{
+ Name: 0x0CF3AD,
+ Type: uint32(SHT_SYMTAB_SHNDX),
+ Off: 0x13ED1C,
+ Size: 0x03FC28,
+ Link: 0xFF0E,
+ Addralign: 0x04,
+ Entsize: 0x04,
+ })
+ // .strtab
+ binary.Write(&buf, binary.LittleEndian, Section32{
+ Name: 0x09,
+ Type: uint32(SHT_STRTAB),
+ Off: 0x17E944,
+ Size: 0x08F74D,
+ Addralign: 0x01,
+ })
+ // .shstrtab
+ binary.Write(&buf, binary.LittleEndian, Section32{
+ Name: 0x11,
+ Type: uint32(SHT_STRTAB),
+ Off: 0x20E091,
+ Size: 0x0CF3BB,
+ Addralign: 0x01,
+ })
+ }
+
+ data := buf.Bytes()
+
+ f, err := NewFile(bytes.NewReader(data))
+ if err != nil {
+ t.Errorf("cannot create file from data: %v", err)
+ }
+ defer f.Close()
+
+ wantFileHeader := FileHeader{
+ Class: ELFCLASS32,
+ Data: ELFDATA2LSB,
+ Version: EV_CURRENT,
+ OSABI: ELFOSABI_NONE,
+ ByteOrder: binary.LittleEndian,
+ Type: ET_REL,
+ Machine: EM_386,
+ }
+ if f.FileHeader != wantFileHeader {
+ t.Errorf("\nhave %#v\nwant %#v\n", f.FileHeader, wantFileHeader)
+ }
+
+ wantSectionNum := 65298
+ if len(f.Sections) != wantSectionNum {
+ t.Errorf("len(Sections) = %d, want %d", len(f.Sections), wantSectionNum)
+ }
+
+ wantSectionHeader := SectionHeader{
+ Name: "section_0007",
+ Type: SHT_PROGBITS,
+ Flags: SHF_WRITE + SHF_ALLOC,
+ Offset: 0x4c,
+ Size: 0x4,
+ Addralign: 0x4,
+ FileSize: 0x4,
+ }
+ if f.Sections[10].SectionHeader != wantSectionHeader {
+ t.Errorf("\nhave %#v\nwant %#v\n", f.Sections[10].SectionHeader, wantSectionHeader)
+ }
+}
+
func TestIssue10996(t *testing.T) {
data := []byte("\u007fELF\x02\x01\x010000000000000" +
"\x010000000000000000000" +