github.com/mtsmfm/go/src@v0.0.0-20221020090648-44bdcb9f8fde/debug/elf/file_test.go (about) 1 // Copyright 2009 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package elf 6 7 import ( 8 "bytes" 9 "compress/gzip" 10 "debug/dwarf" 11 "encoding/binary" 12 "fmt" 13 "io" 14 "math/rand" 15 "net" 16 "os" 17 "path" 18 "reflect" 19 "runtime" 20 "testing" 21 ) 22 23 type fileTest struct { 24 file string 25 hdr FileHeader 26 sections []SectionHeader 27 progs []ProgHeader 28 needed []string 29 } 30 31 var fileTests = []fileTest{ 32 { 33 "testdata/gcc-386-freebsd-exec", 34 FileHeader{ELFCLASS32, ELFDATA2LSB, EV_CURRENT, ELFOSABI_FREEBSD, 0, binary.LittleEndian, ET_EXEC, EM_386, 0x80483cc}, 35 []SectionHeader{ 36 {"", SHT_NULL, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, 37 {".interp", SHT_PROGBITS, SHF_ALLOC, 0x80480d4, 0xd4, 0x15, 0x0, 0x0, 0x1, 0x0, 0x15}, 38 {".hash", SHT_HASH, SHF_ALLOC, 0x80480ec, 0xec, 0x90, 0x3, 0x0, 0x4, 0x4, 0x90}, 39 {".dynsym", SHT_DYNSYM, SHF_ALLOC, 0x804817c, 0x17c, 0x110, 0x4, 0x1, 0x4, 0x10, 0x110}, 40 {".dynstr", SHT_STRTAB, SHF_ALLOC, 0x804828c, 0x28c, 0xbb, 0x0, 0x0, 0x1, 0x0, 0xbb}, 41 {".rel.plt", SHT_REL, SHF_ALLOC, 0x8048348, 0x348, 0x20, 0x3, 0x7, 0x4, 0x8, 0x20}, 42 {".init", SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR, 0x8048368, 0x368, 0x11, 0x0, 0x0, 0x4, 0x0, 0x11}, 43 {".plt", SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR, 0x804837c, 0x37c, 0x50, 0x0, 0x0, 0x4, 0x4, 0x50}, 44 {".text", SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR, 0x80483cc, 0x3cc, 0x180, 0x0, 0x0, 0x4, 0x0, 0x180}, 45 {".fini", SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR, 0x804854c, 0x54c, 0xc, 0x0, 0x0, 0x4, 0x0, 0xc}, 46 {".rodata", SHT_PROGBITS, SHF_ALLOC, 0x8048558, 0x558, 0xa3, 0x0, 0x0, 0x1, 0x0, 0xa3}, 47 {".data", SHT_PROGBITS, SHF_WRITE + SHF_ALLOC, 0x80495fc, 0x5fc, 0xc, 0x0, 0x0, 0x4, 0x0, 0xc}, 48 {".eh_frame", SHT_PROGBITS, SHF_ALLOC, 0x8049608, 0x608, 0x4, 0x0, 0x0, 0x4, 0x0, 0x4}, 49 {".dynamic", SHT_DYNAMIC, SHF_WRITE + SHF_ALLOC, 0x804960c, 0x60c, 0x98, 0x4, 0x0, 0x4, 0x8, 0x98}, 50 {".ctors", SHT_PROGBITS, SHF_WRITE + SHF_ALLOC, 0x80496a4, 0x6a4, 0x8, 0x0, 0x0, 0x4, 0x0, 0x8}, 51 {".dtors", SHT_PROGBITS, SHF_WRITE + SHF_ALLOC, 0x80496ac, 0x6ac, 0x8, 0x0, 0x0, 0x4, 0x0, 0x8}, 52 {".jcr", SHT_PROGBITS, SHF_WRITE + SHF_ALLOC, 0x80496b4, 0x6b4, 0x4, 0x0, 0x0, 0x4, 0x0, 0x4}, 53 {".got", SHT_PROGBITS, SHF_WRITE + SHF_ALLOC, 0x80496b8, 0x6b8, 0x1c, 0x0, 0x0, 0x4, 0x4, 0x1c}, 54 {".bss", SHT_NOBITS, SHF_WRITE + SHF_ALLOC, 0x80496d4, 0x6d4, 0x20, 0x0, 0x0, 0x4, 0x0, 0x20}, 55 {".comment", SHT_PROGBITS, 0x0, 0x0, 0x6d4, 0x12d, 0x0, 0x0, 0x1, 0x0, 0x12d}, 56 {".debug_aranges", SHT_PROGBITS, 0x0, 0x0, 0x801, 0x20, 0x0, 0x0, 0x1, 0x0, 0x20}, 57 {".debug_pubnames", SHT_PROGBITS, 0x0, 0x0, 0x821, 0x1b, 0x0, 0x0, 0x1, 0x0, 0x1b}, 58 {".debug_info", SHT_PROGBITS, 0x0, 0x0, 0x83c, 0x11d, 0x0, 0x0, 0x1, 0x0, 0x11d}, 59 {".debug_abbrev", SHT_PROGBITS, 0x0, 0x0, 0x959, 0x41, 0x0, 0x0, 0x1, 0x0, 0x41}, 60 {".debug_line", SHT_PROGBITS, 0x0, 0x0, 0x99a, 0x35, 0x0, 0x0, 0x1, 0x0, 0x35}, 61 {".debug_frame", SHT_PROGBITS, 0x0, 0x0, 0x9d0, 0x30, 0x0, 0x0, 0x4, 0x0, 0x30}, 62 {".debug_str", SHT_PROGBITS, 0x0, 0x0, 0xa00, 0xd, 0x0, 0x0, 0x1, 0x0, 0xd}, 63 {".shstrtab", SHT_STRTAB, 0x0, 0x0, 0xa0d, 0xf8, 0x0, 0x0, 0x1, 0x0, 0xf8}, 64 {".symtab", SHT_SYMTAB, 0x0, 0x0, 0xfb8, 0x4b0, 0x1d, 0x38, 0x4, 0x10, 0x4b0}, 65 {".strtab", SHT_STRTAB, 0x0, 0x0, 0x1468, 0x206, 0x0, 0x0, 0x1, 0x0, 0x206}, 66 }, 67 []ProgHeader{ 68 {PT_PHDR, PF_R + PF_X, 0x34, 0x8048034, 0x8048034, 0xa0, 0xa0, 0x4}, 69 {PT_INTERP, PF_R, 0xd4, 0x80480d4, 0x80480d4, 0x15, 0x15, 0x1}, 70 {PT_LOAD, PF_R + PF_X, 0x0, 0x8048000, 0x8048000, 0x5fb, 0x5fb, 0x1000}, 71 {PT_LOAD, PF_R + PF_W, 0x5fc, 0x80495fc, 0x80495fc, 0xd8, 0xf8, 0x1000}, 72 {PT_DYNAMIC, PF_R + PF_W, 0x60c, 0x804960c, 0x804960c, 0x98, 0x98, 0x4}, 73 }, 74 []string{"libc.so.6"}, 75 }, 76 { 77 "testdata/gcc-amd64-linux-exec", 78 FileHeader{ELFCLASS64, ELFDATA2LSB, EV_CURRENT, ELFOSABI_NONE, 0, binary.LittleEndian, ET_EXEC, EM_X86_64, 0x4003e0}, 79 []SectionHeader{ 80 {"", SHT_NULL, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, 81 {".interp", SHT_PROGBITS, SHF_ALLOC, 0x400200, 0x200, 0x1c, 0x0, 0x0, 0x1, 0x0, 0x1c}, 82 {".note.ABI-tag", SHT_NOTE, SHF_ALLOC, 0x40021c, 0x21c, 0x20, 0x0, 0x0, 0x4, 0x0, 0x20}, 83 {".hash", SHT_HASH, SHF_ALLOC, 0x400240, 0x240, 0x24, 0x5, 0x0, 0x8, 0x4, 0x24}, 84 {".gnu.hash", SHT_LOOS + 268435446, SHF_ALLOC, 0x400268, 0x268, 0x1c, 0x5, 0x0, 0x8, 0x0, 0x1c}, 85 {".dynsym", SHT_DYNSYM, SHF_ALLOC, 0x400288, 0x288, 0x60, 0x6, 0x1, 0x8, 0x18, 0x60}, 86 {".dynstr", SHT_STRTAB, SHF_ALLOC, 0x4002e8, 0x2e8, 0x3d, 0x0, 0x0, 0x1, 0x0, 0x3d}, 87 {".gnu.version", SHT_HIOS, SHF_ALLOC, 0x400326, 0x326, 0x8, 0x5, 0x0, 0x2, 0x2, 0x8}, 88 {".gnu.version_r", SHT_LOOS + 268435454, SHF_ALLOC, 0x400330, 0x330, 0x20, 0x6, 0x1, 0x8, 0x0, 0x20}, 89 {".rela.dyn", SHT_RELA, SHF_ALLOC, 0x400350, 0x350, 0x18, 0x5, 0x0, 0x8, 0x18, 0x18}, 90 {".rela.plt", SHT_RELA, SHF_ALLOC, 0x400368, 0x368, 0x30, 0x5, 0xc, 0x8, 0x18, 0x30}, 91 {".init", SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR, 0x400398, 0x398, 0x18, 0x0, 0x0, 0x4, 0x0, 0x18}, 92 {".plt", SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR, 0x4003b0, 0x3b0, 0x30, 0x0, 0x0, 0x4, 0x10, 0x30}, 93 {".text", SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR, 0x4003e0, 0x3e0, 0x1b4, 0x0, 0x0, 0x10, 0x0, 0x1b4}, 94 {".fini", SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR, 0x400594, 0x594, 0xe, 0x0, 0x0, 0x4, 0x0, 0xe}, 95 {".rodata", SHT_PROGBITS, SHF_ALLOC, 0x4005a4, 0x5a4, 0x11, 0x0, 0x0, 0x4, 0x0, 0x11}, 96 {".eh_frame_hdr", SHT_PROGBITS, SHF_ALLOC, 0x4005b8, 0x5b8, 0x24, 0x0, 0x0, 0x4, 0x0, 0x24}, 97 {".eh_frame", SHT_PROGBITS, SHF_ALLOC, 0x4005e0, 0x5e0, 0xa4, 0x0, 0x0, 0x8, 0x0, 0xa4}, 98 {".ctors", SHT_PROGBITS, SHF_WRITE + SHF_ALLOC, 0x600688, 0x688, 0x10, 0x0, 0x0, 0x8, 0x0, 0x10}, 99 {".dtors", SHT_PROGBITS, SHF_WRITE + SHF_ALLOC, 0x600698, 0x698, 0x10, 0x0, 0x0, 0x8, 0x0, 0x10}, 100 {".jcr", SHT_PROGBITS, SHF_WRITE + SHF_ALLOC, 0x6006a8, 0x6a8, 0x8, 0x0, 0x0, 0x8, 0x0, 0x8}, 101 {".dynamic", SHT_DYNAMIC, SHF_WRITE + SHF_ALLOC, 0x6006b0, 0x6b0, 0x1a0, 0x6, 0x0, 0x8, 0x10, 0x1a0}, 102 {".got", SHT_PROGBITS, SHF_WRITE + SHF_ALLOC, 0x600850, 0x850, 0x8, 0x0, 0x0, 0x8, 0x8, 0x8}, 103 {".got.plt", SHT_PROGBITS, SHF_WRITE + SHF_ALLOC, 0x600858, 0x858, 0x28, 0x0, 0x0, 0x8, 0x8, 0x28}, 104 {".data", SHT_PROGBITS, SHF_WRITE + SHF_ALLOC, 0x600880, 0x880, 0x18, 0x0, 0x0, 0x8, 0x0, 0x18}, 105 {".bss", SHT_NOBITS, SHF_WRITE + SHF_ALLOC, 0x600898, 0x898, 0x8, 0x0, 0x0, 0x4, 0x0, 0x8}, 106 {".comment", SHT_PROGBITS, 0x0, 0x0, 0x898, 0x126, 0x0, 0x0, 0x1, 0x0, 0x126}, 107 {".debug_aranges", SHT_PROGBITS, 0x0, 0x0, 0x9c0, 0x90, 0x0, 0x0, 0x10, 0x0, 0x90}, 108 {".debug_pubnames", SHT_PROGBITS, 0x0, 0x0, 0xa50, 0x25, 0x0, 0x0, 0x1, 0x0, 0x25}, 109 {".debug_info", SHT_PROGBITS, 0x0, 0x0, 0xa75, 0x1a7, 0x0, 0x0, 0x1, 0x0, 0x1a7}, 110 {".debug_abbrev", SHT_PROGBITS, 0x0, 0x0, 0xc1c, 0x6f, 0x0, 0x0, 0x1, 0x0, 0x6f}, 111 {".debug_line", SHT_PROGBITS, 0x0, 0x0, 0xc8b, 0x13f, 0x0, 0x0, 0x1, 0x0, 0x13f}, 112 {".debug_str", SHT_PROGBITS, SHF_MERGE + SHF_STRINGS, 0x0, 0xdca, 0xb1, 0x0, 0x0, 0x1, 0x1, 0xb1}, 113 {".debug_ranges", SHT_PROGBITS, 0x0, 0x0, 0xe80, 0x90, 0x0, 0x0, 0x10, 0x0, 0x90}, 114 {".shstrtab", SHT_STRTAB, 0x0, 0x0, 0xf10, 0x149, 0x0, 0x0, 0x1, 0x0, 0x149}, 115 {".symtab", SHT_SYMTAB, 0x0, 0x0, 0x19a0, 0x6f0, 0x24, 0x39, 0x8, 0x18, 0x6f0}, 116 {".strtab", SHT_STRTAB, 0x0, 0x0, 0x2090, 0x1fc, 0x0, 0x0, 0x1, 0x0, 0x1fc}, 117 }, 118 []ProgHeader{ 119 {PT_PHDR, PF_R + PF_X, 0x40, 0x400040, 0x400040, 0x1c0, 0x1c0, 0x8}, 120 {PT_INTERP, PF_R, 0x200, 0x400200, 0x400200, 0x1c, 0x1c, 1}, 121 {PT_LOAD, PF_R + PF_X, 0x0, 0x400000, 0x400000, 0x684, 0x684, 0x200000}, 122 {PT_LOAD, PF_R + PF_W, 0x688, 0x600688, 0x600688, 0x210, 0x218, 0x200000}, 123 {PT_DYNAMIC, PF_R + PF_W, 0x6b0, 0x6006b0, 0x6006b0, 0x1a0, 0x1a0, 0x8}, 124 {PT_NOTE, PF_R, 0x21c, 0x40021c, 0x40021c, 0x20, 0x20, 0x4}, 125 {PT_LOOS + 0x474E550, PF_R, 0x5b8, 0x4005b8, 0x4005b8, 0x24, 0x24, 0x4}, 126 {PT_LOOS + 0x474E551, PF_R + PF_W, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8}, 127 }, 128 []string{"libc.so.6"}, 129 }, 130 { 131 "testdata/hello-world-core.gz", 132 FileHeader{ELFCLASS64, ELFDATA2LSB, EV_CURRENT, ELFOSABI_NONE, 0x0, binary.LittleEndian, ET_CORE, EM_X86_64, 0x0}, 133 []SectionHeader{}, 134 []ProgHeader{ 135 {Type: PT_NOTE, Flags: 0x0, Off: 0x3f8, Vaddr: 0x0, Paddr: 0x0, Filesz: 0x8ac, Memsz: 0x0, Align: 0x0}, 136 {Type: PT_LOAD, Flags: PF_X + PF_R, Off: 0x1000, Vaddr: 0x400000, Paddr: 0x0, Filesz: 0x0, Memsz: 0x1000, Align: 0x1000}, 137 {Type: PT_LOAD, Flags: PF_R, Off: 0x1000, Vaddr: 0x401000, Paddr: 0x0, Filesz: 0x1000, Memsz: 0x1000, Align: 0x1000}, 138 {Type: PT_LOAD, Flags: PF_W + PF_R, Off: 0x2000, Vaddr: 0x402000, Paddr: 0x0, Filesz: 0x1000, Memsz: 0x1000, Align: 0x1000}, 139 {Type: PT_LOAD, Flags: PF_X + PF_R, Off: 0x3000, Vaddr: 0x7f54078b8000, Paddr: 0x0, Filesz: 0x0, Memsz: 0x1b5000, Align: 0x1000}, 140 {Type: PT_LOAD, Flags: 0x0, Off: 0x3000, Vaddr: 0x7f5407a6d000, Paddr: 0x0, Filesz: 0x0, Memsz: 0x1ff000, Align: 0x1000}, 141 {Type: PT_LOAD, Flags: PF_R, Off: 0x3000, Vaddr: 0x7f5407c6c000, Paddr: 0x0, Filesz: 0x4000, Memsz: 0x4000, Align: 0x1000}, 142 {Type: PT_LOAD, Flags: PF_W + PF_R, Off: 0x7000, Vaddr: 0x7f5407c70000, Paddr: 0x0, Filesz: 0x2000, Memsz: 0x2000, Align: 0x1000}, 143 {Type: PT_LOAD, Flags: PF_W + PF_R, Off: 0x9000, Vaddr: 0x7f5407c72000, Paddr: 0x0, Filesz: 0x5000, Memsz: 0x5000, Align: 0x1000}, 144 {Type: PT_LOAD, Flags: PF_X + PF_R, Off: 0xe000, Vaddr: 0x7f5407c77000, Paddr: 0x0, Filesz: 0x0, Memsz: 0x22000, Align: 0x1000}, 145 {Type: PT_LOAD, Flags: PF_W + PF_R, Off: 0xe000, Vaddr: 0x7f5407e81000, Paddr: 0x0, Filesz: 0x3000, Memsz: 0x3000, Align: 0x1000}, 146 {Type: PT_LOAD, Flags: PF_W + PF_R, Off: 0x11000, Vaddr: 0x7f5407e96000, Paddr: 0x0, Filesz: 0x3000, Memsz: 0x3000, Align: 0x1000}, 147 {Type: PT_LOAD, Flags: PF_R, Off: 0x14000, Vaddr: 0x7f5407e99000, Paddr: 0x0, Filesz: 0x1000, Memsz: 0x1000, Align: 0x1000}, 148 {Type: PT_LOAD, Flags: PF_W + PF_R, Off: 0x15000, Vaddr: 0x7f5407e9a000, Paddr: 0x0, Filesz: 0x2000, Memsz: 0x2000, Align: 0x1000}, 149 {Type: PT_LOAD, Flags: PF_W + PF_R, Off: 0x17000, Vaddr: 0x7fff79972000, Paddr: 0x0, Filesz: 0x23000, Memsz: 0x23000, Align: 0x1000}, 150 {Type: PT_LOAD, Flags: PF_X + PF_R, Off: 0x3a000, Vaddr: 0x7fff799f8000, Paddr: 0x0, Filesz: 0x1000, Memsz: 0x1000, Align: 0x1000}, 151 {Type: PT_LOAD, Flags: PF_X + PF_R, Off: 0x3b000, Vaddr: 0xffffffffff600000, Paddr: 0x0, Filesz: 0x1000, Memsz: 0x1000, Align: 0x1000}, 152 }, 153 nil, 154 }, 155 { 156 "testdata/compressed-32.obj", 157 FileHeader{ELFCLASS32, ELFDATA2LSB, EV_CURRENT, ELFOSABI_NONE, 0x0, binary.LittleEndian, ET_REL, EM_386, 0x0}, 158 []SectionHeader{ 159 {"", SHT_NULL, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, 160 {".text", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR, 0x0, 0x34, 0x17, 0x0, 0x0, 0x1, 0x0, 0x17}, 161 {".rel.text", SHT_REL, SHF_INFO_LINK, 0x0, 0x3dc, 0x10, 0x13, 0x1, 0x4, 0x8, 0x10}, 162 {".data", SHT_PROGBITS, SHF_WRITE | SHF_ALLOC, 0x0, 0x4b, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0}, 163 {".bss", SHT_NOBITS, SHF_WRITE | SHF_ALLOC, 0x0, 0x4b, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0}, 164 {".rodata", SHT_PROGBITS, SHF_ALLOC, 0x0, 0x4b, 0xd, 0x0, 0x0, 0x1, 0x0, 0xd}, 165 {".debug_info", SHT_PROGBITS, SHF_COMPRESSED, 0x0, 0x58, 0xb4, 0x0, 0x0, 0x1, 0x0, 0x84}, 166 {".rel.debug_info", SHT_REL, SHF_INFO_LINK, 0x0, 0x3ec, 0xa0, 0x13, 0x6, 0x4, 0x8, 0xa0}, 167 {".debug_abbrev", SHT_PROGBITS, 0x0, 0x0, 0xdc, 0x5a, 0x0, 0x0, 0x1, 0x0, 0x5a}, 168 {".debug_aranges", SHT_PROGBITS, 0x0, 0x0, 0x136, 0x20, 0x0, 0x0, 0x1, 0x0, 0x20}, 169 {".rel.debug_aranges", SHT_REL, SHF_INFO_LINK, 0x0, 0x48c, 0x10, 0x13, 0x9, 0x4, 0x8, 0x10}, 170 {".debug_line", SHT_PROGBITS, 0x0, 0x0, 0x156, 0x5c, 0x0, 0x0, 0x1, 0x0, 0x5c}, 171 {".rel.debug_line", SHT_REL, SHF_INFO_LINK, 0x0, 0x49c, 0x8, 0x13, 0xb, 0x4, 0x8, 0x8}, 172 {".debug_str", SHT_PROGBITS, SHF_MERGE | SHF_STRINGS | SHF_COMPRESSED, 0x0, 0x1b2, 0x10f, 0x0, 0x0, 0x1, 0x1, 0xb3}, 173 {".comment", SHT_PROGBITS, SHF_MERGE | SHF_STRINGS, 0x0, 0x265, 0x2a, 0x0, 0x0, 0x1, 0x1, 0x2a}, 174 {".note.GNU-stack", SHT_PROGBITS, 0x0, 0x0, 0x28f, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0}, 175 {".eh_frame", SHT_PROGBITS, SHF_ALLOC, 0x0, 0x290, 0x38, 0x0, 0x0, 0x4, 0x0, 0x38}, 176 {".rel.eh_frame", SHT_REL, SHF_INFO_LINK, 0x0, 0x4a4, 0x8, 0x13, 0x10, 0x4, 0x8, 0x8}, 177 {".shstrtab", SHT_STRTAB, 0x0, 0x0, 0x4ac, 0xab, 0x0, 0x0, 0x1, 0x0, 0xab}, 178 {".symtab", SHT_SYMTAB, 0x0, 0x0, 0x2c8, 0x100, 0x14, 0xe, 0x4, 0x10, 0x100}, 179 {".strtab", SHT_STRTAB, 0x0, 0x0, 0x3c8, 0x13, 0x0, 0x0, 0x1, 0x0, 0x13}, 180 }, 181 []ProgHeader{}, 182 nil, 183 }, 184 { 185 "testdata/compressed-64.obj", 186 FileHeader{ELFCLASS64, ELFDATA2LSB, EV_CURRENT, ELFOSABI_NONE, 0x0, binary.LittleEndian, ET_REL, EM_X86_64, 0x0}, 187 []SectionHeader{ 188 {"", SHT_NULL, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, 189 {".text", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR, 0x0, 0x40, 0x1b, 0x0, 0x0, 0x1, 0x0, 0x1b}, 190 {".rela.text", SHT_RELA, SHF_INFO_LINK, 0x0, 0x488, 0x30, 0x13, 0x1, 0x8, 0x18, 0x30}, 191 {".data", SHT_PROGBITS, SHF_WRITE | SHF_ALLOC, 0x0, 0x5b, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0}, 192 {".bss", SHT_NOBITS, SHF_WRITE | SHF_ALLOC, 0x0, 0x5b, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0}, 193 {".rodata", SHT_PROGBITS, SHF_ALLOC, 0x0, 0x5b, 0xd, 0x0, 0x0, 0x1, 0x0, 0xd}, 194 {".debug_info", SHT_PROGBITS, SHF_COMPRESSED, 0x0, 0x68, 0xba, 0x0, 0x0, 0x1, 0x0, 0x72}, 195 {".rela.debug_info", SHT_RELA, SHF_INFO_LINK, 0x0, 0x4b8, 0x1c8, 0x13, 0x6, 0x8, 0x18, 0x1c8}, 196 {".debug_abbrev", SHT_PROGBITS, 0x0, 0x0, 0xda, 0x5c, 0x0, 0x0, 0x1, 0x0, 0x5c}, 197 {".debug_aranges", SHT_PROGBITS, SHF_COMPRESSED, 0x0, 0x136, 0x30, 0x0, 0x0, 0x1, 0x0, 0x2f}, 198 {".rela.debug_aranges", SHT_RELA, SHF_INFO_LINK, 0x0, 0x680, 0x30, 0x13, 0x9, 0x8, 0x18, 0x30}, 199 {".debug_line", SHT_PROGBITS, 0x0, 0x0, 0x165, 0x60, 0x0, 0x0, 0x1, 0x0, 0x60}, 200 {".rela.debug_line", SHT_RELA, SHF_INFO_LINK, 0x0, 0x6b0, 0x18, 0x13, 0xb, 0x8, 0x18, 0x18}, 201 {".debug_str", SHT_PROGBITS, SHF_MERGE | SHF_STRINGS | SHF_COMPRESSED, 0x0, 0x1c5, 0x104, 0x0, 0x0, 0x1, 0x1, 0xc3}, 202 {".comment", SHT_PROGBITS, SHF_MERGE | SHF_STRINGS, 0x0, 0x288, 0x2a, 0x0, 0x0, 0x1, 0x1, 0x2a}, 203 {".note.GNU-stack", SHT_PROGBITS, 0x0, 0x0, 0x2b2, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0}, 204 {".eh_frame", SHT_PROGBITS, SHF_ALLOC, 0x0, 0x2b8, 0x38, 0x0, 0x0, 0x8, 0x0, 0x38}, 205 {".rela.eh_frame", SHT_RELA, SHF_INFO_LINK, 0x0, 0x6c8, 0x18, 0x13, 0x10, 0x8, 0x18, 0x18}, 206 {".shstrtab", SHT_STRTAB, 0x0, 0x0, 0x6e0, 0xb0, 0x0, 0x0, 0x1, 0x0, 0xb0}, 207 {".symtab", SHT_SYMTAB, 0x0, 0x0, 0x2f0, 0x180, 0x14, 0xe, 0x8, 0x18, 0x180}, 208 {".strtab", SHT_STRTAB, 0x0, 0x0, 0x470, 0x13, 0x0, 0x0, 0x1, 0x0, 0x13}, 209 }, 210 []ProgHeader{}, 211 nil, 212 }, 213 } 214 215 func TestOpen(t *testing.T) { 216 for i := range fileTests { 217 tt := &fileTests[i] 218 219 var f *File 220 var err error 221 if path.Ext(tt.file) == ".gz" { 222 var r io.ReaderAt 223 if r, err = decompress(tt.file); err == nil { 224 f, err = NewFile(r) 225 } 226 } else { 227 f, err = Open(tt.file) 228 } 229 if err != nil { 230 t.Errorf("cannot open file %s: %v", tt.file, err) 231 continue 232 } 233 defer f.Close() 234 if f.FileHeader != tt.hdr { 235 t.Errorf("open %s:\n\thave %#v\n\twant %#v\n", tt.file, f.FileHeader, tt.hdr) 236 continue 237 } 238 for i, s := range f.Sections { 239 if i >= len(tt.sections) { 240 break 241 } 242 sh := tt.sections[i] 243 if s.SectionHeader != sh { 244 t.Errorf("open %s, section %d:\n\thave %#v\n\twant %#v\n", tt.file, i, s.SectionHeader, sh) 245 } 246 } 247 for i, p := range f.Progs { 248 if i >= len(tt.progs) { 249 break 250 } 251 ph := tt.progs[i] 252 if p.ProgHeader != ph { 253 t.Errorf("open %s, program %d:\n\thave %#v\n\twant %#v\n", tt.file, i, p.ProgHeader, ph) 254 } 255 } 256 tn := len(tt.sections) 257 fn := len(f.Sections) 258 if tn != fn { 259 t.Errorf("open %s: len(Sections) = %d, want %d", tt.file, fn, tn) 260 } 261 tn = len(tt.progs) 262 fn = len(f.Progs) 263 if tn != fn { 264 t.Errorf("open %s: len(Progs) = %d, want %d", tt.file, fn, tn) 265 } 266 tl := tt.needed 267 fl, err := f.ImportedLibraries() 268 if err != nil { 269 t.Error(err) 270 } 271 if !reflect.DeepEqual(tl, fl) { 272 t.Errorf("open %s: DT_NEEDED = %v, want %v", tt.file, tl, fl) 273 } 274 } 275 } 276 277 // elf.NewFile requires io.ReaderAt, which compress/gzip cannot 278 // provide. Decompress the file to a bytes.Reader. 279 func decompress(gz string) (io.ReaderAt, error) { 280 in, err := os.Open(gz) 281 if err != nil { 282 return nil, err 283 } 284 defer in.Close() 285 r, err := gzip.NewReader(in) 286 if err != nil { 287 return nil, err 288 } 289 var out bytes.Buffer 290 _, err = io.Copy(&out, r) 291 return bytes.NewReader(out.Bytes()), err 292 } 293 294 type relocationTestEntry struct { 295 entryNumber int 296 entry *dwarf.Entry 297 pcRanges [][2]uint64 298 } 299 300 type relocationTest struct { 301 file string 302 entries []relocationTestEntry 303 } 304 305 var relocationTests = []relocationTest{ 306 { 307 "testdata/go-relocation-test-gcc441-x86-64.obj", 308 []relocationTestEntry{ 309 { 310 entry: &dwarf.Entry{ 311 Offset: 0xb, 312 Tag: dwarf.TagCompileUnit, 313 Children: true, 314 Field: []dwarf.Field{ 315 {Attr: dwarf.AttrProducer, Val: "GNU C 4.4.1", Class: dwarf.ClassString}, 316 {Attr: dwarf.AttrLanguage, Val: int64(1), Class: dwarf.ClassConstant}, 317 {Attr: dwarf.AttrName, Val: "go-relocation-test.c", Class: dwarf.ClassString}, 318 {Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString}, 319 {Attr: dwarf.AttrLowpc, Val: uint64(0x0), Class: dwarf.ClassAddress}, 320 {Attr: dwarf.AttrHighpc, Val: uint64(0x6), Class: dwarf.ClassAddress}, 321 {Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr}, 322 }, 323 }, 324 pcRanges: [][2]uint64{{0x0, 0x6}}, 325 }, 326 }, 327 }, 328 { 329 "testdata/go-relocation-test-gcc441-x86.obj", 330 []relocationTestEntry{ 331 { 332 entry: &dwarf.Entry{ 333 Offset: 0xb, 334 Tag: dwarf.TagCompileUnit, 335 Children: true, 336 Field: []dwarf.Field{ 337 {Attr: dwarf.AttrProducer, Val: "GNU C 4.4.1", Class: dwarf.ClassString}, 338 {Attr: dwarf.AttrLanguage, Val: int64(1), Class: dwarf.ClassConstant}, 339 {Attr: dwarf.AttrName, Val: "t.c", Class: dwarf.ClassString}, 340 {Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString}, 341 {Attr: dwarf.AttrLowpc, Val: uint64(0x0), Class: dwarf.ClassAddress}, 342 {Attr: dwarf.AttrHighpc, Val: uint64(0x5), Class: dwarf.ClassAddress}, 343 {Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr}, 344 }, 345 }, 346 pcRanges: [][2]uint64{{0x0, 0x5}}, 347 }, 348 }, 349 }, 350 { 351 "testdata/go-relocation-test-gcc424-x86-64.obj", 352 []relocationTestEntry{ 353 { 354 entry: &dwarf.Entry{ 355 Offset: 0xb, 356 Tag: dwarf.TagCompileUnit, 357 Children: true, 358 Field: []dwarf.Field{ 359 {Attr: dwarf.AttrProducer, Val: "GNU C 4.2.4 (Ubuntu 4.2.4-1ubuntu4)", Class: dwarf.ClassString}, 360 {Attr: dwarf.AttrLanguage, Val: int64(1), Class: dwarf.ClassConstant}, 361 {Attr: dwarf.AttrName, Val: "go-relocation-test-gcc424.c", Class: dwarf.ClassString}, 362 {Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString}, 363 {Attr: dwarf.AttrLowpc, Val: uint64(0x0), Class: dwarf.ClassAddress}, 364 {Attr: dwarf.AttrHighpc, Val: uint64(0x6), Class: dwarf.ClassAddress}, 365 {Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr}, 366 }, 367 }, 368 pcRanges: [][2]uint64{{0x0, 0x6}}, 369 }, 370 }, 371 }, 372 { 373 "testdata/go-relocation-test-gcc482-aarch64.obj", 374 []relocationTestEntry{ 375 { 376 entry: &dwarf.Entry{ 377 Offset: 0xb, 378 Tag: dwarf.TagCompileUnit, 379 Children: true, 380 Field: []dwarf.Field{ 381 {Attr: dwarf.AttrProducer, Val: "GNU C 4.8.2 -g -fstack-protector", Class: dwarf.ClassString}, 382 {Attr: dwarf.AttrLanguage, Val: int64(1), Class: dwarf.ClassConstant}, 383 {Attr: dwarf.AttrName, Val: "go-relocation-test-gcc482.c", Class: dwarf.ClassString}, 384 {Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString}, 385 {Attr: dwarf.AttrLowpc, Val: uint64(0x0), Class: dwarf.ClassAddress}, 386 {Attr: dwarf.AttrHighpc, Val: int64(0x24), Class: dwarf.ClassConstant}, 387 {Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr}, 388 }, 389 }, 390 pcRanges: [][2]uint64{{0x0, 0x24}}, 391 }, 392 }, 393 }, 394 { 395 "testdata/go-relocation-test-gcc492-arm.obj", 396 []relocationTestEntry{ 397 { 398 entry: &dwarf.Entry{ 399 Offset: 0xb, 400 Tag: dwarf.TagCompileUnit, 401 Children: true, 402 Field: []dwarf.Field{ 403 {Attr: dwarf.AttrProducer, Val: "GNU C 4.9.2 20141224 (prerelease) -march=armv7-a -mfloat-abi=hard -mfpu=vfpv3-d16 -mtls-dialect=gnu -g", Class: dwarf.ClassString}, 404 {Attr: dwarf.AttrLanguage, Val: int64(1), Class: dwarf.ClassConstant}, 405 {Attr: dwarf.AttrName, Val: "go-relocation-test-gcc492.c", Class: dwarf.ClassString}, 406 {Attr: dwarf.AttrCompDir, Val: "/root/go/src/debug/elf/testdata", Class: dwarf.ClassString}, 407 {Attr: dwarf.AttrLowpc, Val: uint64(0x0), Class: dwarf.ClassAddress}, 408 {Attr: dwarf.AttrHighpc, Val: int64(0x28), Class: dwarf.ClassConstant}, 409 {Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr}, 410 }, 411 }, 412 pcRanges: [][2]uint64{{0x0, 0x28}}, 413 }, 414 }, 415 }, 416 { 417 "testdata/go-relocation-test-clang-arm.obj", 418 []relocationTestEntry{ 419 { 420 entry: &dwarf.Entry{ 421 Offset: 0xb, 422 Tag: dwarf.TagCompileUnit, 423 Children: true, 424 Field: []dwarf.Field{ 425 {Attr: dwarf.AttrProducer, Val: "Debian clang version 3.5.0-10 (tags/RELEASE_350/final) (based on LLVM 3.5.0)", Class: dwarf.ClassString}, 426 {Attr: dwarf.AttrLanguage, Val: int64(12), Class: dwarf.ClassConstant}, 427 {Attr: dwarf.AttrName, Val: "hello.c", Class: dwarf.ClassString}, 428 {Attr: dwarf.AttrStmtList, Val: int64(0x0), Class: dwarf.ClassLinePtr}, 429 {Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString}, 430 {Attr: dwarf.AttrLowpc, Val: uint64(0x0), Class: dwarf.ClassAddress}, 431 {Attr: dwarf.AttrHighpc, Val: int64(0x30), Class: dwarf.ClassConstant}, 432 }, 433 }, 434 pcRanges: [][2]uint64{{0x0, 0x30}}, 435 }, 436 }, 437 }, 438 { 439 "testdata/go-relocation-test-gcc5-ppc.obj", 440 []relocationTestEntry{ 441 { 442 entry: &dwarf.Entry{ 443 Offset: 0xb, 444 Tag: dwarf.TagCompileUnit, 445 Children: true, 446 Field: []dwarf.Field{ 447 {Attr: dwarf.AttrProducer, Val: "GNU C11 5.0.0 20150116 (experimental) -Asystem=linux -Asystem=unix -Asystem=posix -g", Class: dwarf.ClassString}, 448 {Attr: dwarf.AttrLanguage, Val: int64(12), Class: dwarf.ClassConstant}, 449 {Attr: dwarf.AttrName, Val: "go-relocation-test-gcc5-ppc.c", Class: dwarf.ClassString}, 450 {Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString}, 451 {Attr: dwarf.AttrLowpc, Val: uint64(0x0), Class: dwarf.ClassAddress}, 452 {Attr: dwarf.AttrHighpc, Val: int64(0x44), Class: dwarf.ClassConstant}, 453 {Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr}, 454 }, 455 }, 456 pcRanges: [][2]uint64{{0x0, 0x44}}, 457 }, 458 }, 459 }, 460 { 461 "testdata/go-relocation-test-gcc482-ppc64le.obj", 462 []relocationTestEntry{ 463 { 464 entry: &dwarf.Entry{ 465 Offset: 0xb, 466 Tag: dwarf.TagCompileUnit, 467 Children: true, 468 Field: []dwarf.Field{ 469 {Attr: dwarf.AttrProducer, Val: "GNU C 4.8.2 -Asystem=linux -Asystem=unix -Asystem=posix -msecure-plt -mtune=power8 -mcpu=power7 -gdwarf-2 -fstack-protector", Class: dwarf.ClassString}, 470 {Attr: dwarf.AttrLanguage, Val: int64(1), Class: dwarf.ClassConstant}, 471 {Attr: dwarf.AttrName, Val: "go-relocation-test-gcc482-ppc64le.c", Class: dwarf.ClassString}, 472 {Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString}, 473 {Attr: dwarf.AttrLowpc, Val: uint64(0x0), Class: dwarf.ClassAddress}, 474 {Attr: dwarf.AttrHighpc, Val: uint64(0x24), Class: dwarf.ClassAddress}, 475 {Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr}, 476 }, 477 }, 478 pcRanges: [][2]uint64{{0x0, 0x24}}, 479 }, 480 }, 481 }, 482 { 483 "testdata/go-relocation-test-gcc492-mips64.obj", 484 []relocationTestEntry{ 485 { 486 entry: &dwarf.Entry{ 487 Offset: 0xb, 488 Tag: dwarf.TagCompileUnit, 489 Children: true, 490 Field: []dwarf.Field{ 491 {Attr: dwarf.AttrProducer, Val: "GNU C 4.9.2 -meb -mabi=64 -march=mips3 -mtune=mips64 -mllsc -mno-shared -g", Class: dwarf.ClassString}, 492 {Attr: dwarf.AttrLanguage, Val: int64(1), Class: dwarf.ClassConstant}, 493 {Attr: dwarf.AttrName, Val: "hello.c", Class: dwarf.ClassString}, 494 {Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString}, 495 {Attr: dwarf.AttrLowpc, Val: uint64(0x0), Class: dwarf.ClassAddress}, 496 {Attr: dwarf.AttrHighpc, Val: int64(0x64), Class: dwarf.ClassConstant}, 497 {Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr}, 498 }, 499 }, 500 pcRanges: [][2]uint64{{0x0, 0x64}}, 501 }, 502 }, 503 }, 504 { 505 "testdata/go-relocation-test-gcc531-s390x.obj", 506 []relocationTestEntry{ 507 { 508 entry: &dwarf.Entry{ 509 Offset: 0xb, 510 Tag: dwarf.TagCompileUnit, 511 Children: true, 512 Field: []dwarf.Field{ 513 {Attr: dwarf.AttrProducer, Val: "GNU C11 5.3.1 20160316 -march=zEC12 -m64 -mzarch -g -fstack-protector-strong", Class: dwarf.ClassString}, 514 {Attr: dwarf.AttrLanguage, Val: int64(12), Class: dwarf.ClassConstant}, 515 {Attr: dwarf.AttrName, Val: "hello.c", Class: dwarf.ClassString}, 516 {Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString}, 517 {Attr: dwarf.AttrLowpc, Val: uint64(0x0), Class: dwarf.ClassAddress}, 518 {Attr: dwarf.AttrHighpc, Val: int64(0x3a), Class: dwarf.ClassConstant}, 519 {Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr}, 520 }, 521 }, 522 pcRanges: [][2]uint64{{0x0, 0x3a}}, 523 }, 524 }, 525 }, 526 { 527 "testdata/go-relocation-test-gcc620-sparc64.obj", 528 []relocationTestEntry{ 529 { 530 entry: &dwarf.Entry{ 531 Offset: 0xb, 532 Tag: dwarf.TagCompileUnit, 533 Children: true, 534 Field: []dwarf.Field{ 535 {Attr: dwarf.AttrProducer, Val: "GNU C11 6.2.0 20160914 -mcpu=v9 -g -fstack-protector-strong", Class: dwarf.ClassString}, 536 {Attr: dwarf.AttrLanguage, Val: int64(12), Class: dwarf.ClassConstant}, 537 {Attr: dwarf.AttrName, Val: "hello.c", Class: dwarf.ClassString}, 538 {Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString}, 539 {Attr: dwarf.AttrLowpc, Val: uint64(0x0), Class: dwarf.ClassAddress}, 540 {Attr: dwarf.AttrHighpc, Val: int64(0x2c), Class: dwarf.ClassConstant}, 541 {Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr}, 542 }, 543 }, 544 pcRanges: [][2]uint64{{0x0, 0x2c}}, 545 }, 546 }, 547 }, 548 { 549 "testdata/go-relocation-test-gcc492-mipsle.obj", 550 []relocationTestEntry{ 551 { 552 entry: &dwarf.Entry{ 553 Offset: 0xb, 554 Tag: dwarf.TagCompileUnit, 555 Children: true, 556 Field: []dwarf.Field{ 557 {Attr: dwarf.AttrProducer, Val: "GNU C 4.9.2 -mel -march=mips2 -mtune=mips32 -mllsc -mno-shared -mabi=32 -g", Class: dwarf.ClassString}, 558 {Attr: dwarf.AttrLanguage, Val: int64(1), Class: dwarf.ClassConstant}, 559 {Attr: dwarf.AttrName, Val: "hello.c", Class: dwarf.ClassString}, 560 {Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString}, 561 {Attr: dwarf.AttrLowpc, Val: uint64(0x0), Class: dwarf.ClassAddress}, 562 {Attr: dwarf.AttrHighpc, Val: int64(0x58), Class: dwarf.ClassConstant}, 563 {Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr}, 564 }, 565 }, 566 pcRanges: [][2]uint64{{0x0, 0x58}}, 567 }, 568 }, 569 }, 570 { 571 "testdata/go-relocation-test-gcc540-mips.obj", 572 []relocationTestEntry{ 573 { 574 entry: &dwarf.Entry{ 575 Offset: 0xb, 576 Tag: dwarf.TagCompileUnit, 577 Children: true, 578 Field: []dwarf.Field{ 579 {Attr: dwarf.AttrProducer, Val: "GNU C11 5.4.0 20160609 -meb -mips32 -mtune=mips32r2 -mfpxx -mllsc -mno-shared -mabi=32 -g -gdwarf-2", Class: dwarf.ClassString}, 580 {Attr: dwarf.AttrLanguage, Val: int64(12), Class: dwarf.ClassConstant}, 581 {Attr: dwarf.AttrName, Val: "hello.c", Class: dwarf.ClassString}, 582 {Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString}, 583 {Attr: dwarf.AttrLowpc, Val: uint64(0x0), Class: dwarf.ClassAddress}, 584 {Attr: dwarf.AttrHighpc, Val: uint64(0x5c), Class: dwarf.ClassAddress}, 585 {Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr}, 586 }, 587 }, 588 pcRanges: [][2]uint64{{0x0, 0x5c}}, 589 }, 590 }, 591 }, 592 { 593 "testdata/go-relocation-test-gcc493-mips64le.obj", 594 []relocationTestEntry{ 595 { 596 entry: &dwarf.Entry{ 597 Offset: 0xb, 598 Tag: dwarf.TagCompileUnit, 599 Children: true, 600 Field: []dwarf.Field{ 601 {Attr: dwarf.AttrProducer, Val: "GNU C 4.9.3 -mel -mabi=64 -mllsc -mno-shared -g -fstack-protector-strong", Class: dwarf.ClassString}, 602 {Attr: dwarf.AttrLanguage, Val: int64(1), Class: dwarf.ClassConstant}, 603 {Attr: dwarf.AttrName, Val: "hello.c", Class: dwarf.ClassString}, 604 {Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString}, 605 {Attr: dwarf.AttrLowpc, Val: uint64(0x0), Class: dwarf.ClassAddress}, 606 {Attr: dwarf.AttrHighpc, Val: int64(0x64), Class: dwarf.ClassConstant}, 607 {Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr}, 608 }, 609 }, 610 pcRanges: [][2]uint64{{0x0, 0x64}}, 611 }, 612 }, 613 }, 614 { 615 "testdata/go-relocation-test-gcc720-riscv64.obj", 616 []relocationTestEntry{ 617 { 618 entry: &dwarf.Entry{ 619 Offset: 0xb, 620 Tag: dwarf.TagCompileUnit, 621 Children: true, 622 Field: []dwarf.Field{ 623 {Attr: dwarf.AttrProducer, Val: "GNU C11 7.2.0 -march=rv64imafdc -mabi=lp64d -g -gdwarf-2", Class: dwarf.ClassString}, 624 {Attr: dwarf.AttrLanguage, Val: int64(12), Class: dwarf.ClassConstant}, 625 {Attr: dwarf.AttrName, Val: "hello.c", Class: dwarf.ClassString}, 626 {Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString}, 627 {Attr: dwarf.AttrLowpc, Val: uint64(0x0), Class: dwarf.ClassAddress}, 628 {Attr: dwarf.AttrHighpc, Val: uint64(0x2c), Class: dwarf.ClassAddress}, 629 {Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr}, 630 }, 631 }, 632 pcRanges: [][2]uint64{{0x0, 0x2c}}, 633 }, 634 }, 635 }, 636 { 637 "testdata/go-relocation-test-clang-x86.obj", 638 []relocationTestEntry{ 639 { 640 entry: &dwarf.Entry{ 641 Offset: 0xb, 642 Tag: dwarf.TagCompileUnit, 643 Children: true, 644 Field: []dwarf.Field{ 645 {Attr: dwarf.AttrProducer, Val: "clang version google3-trunk (trunk r209387)", Class: dwarf.ClassString}, 646 {Attr: dwarf.AttrLanguage, Val: int64(12), Class: dwarf.ClassConstant}, 647 {Attr: dwarf.AttrName, Val: "go-relocation-test-clang.c", Class: dwarf.ClassString}, 648 {Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr}, 649 {Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString}, 650 }, 651 }, 652 }, 653 }, 654 }, 655 { 656 "testdata/gcc-amd64-openbsd-debug-with-rela.obj", 657 []relocationTestEntry{ 658 { 659 entryNumber: 203, 660 entry: &dwarf.Entry{ 661 Offset: 0xc62, 662 Tag: dwarf.TagMember, 663 Children: false, 664 Field: []dwarf.Field{ 665 {Attr: dwarf.AttrName, Val: "it_interval", Class: dwarf.ClassString}, 666 {Attr: dwarf.AttrDeclFile, Val: int64(7), Class: dwarf.ClassConstant}, 667 {Attr: dwarf.AttrDeclLine, Val: int64(236), Class: dwarf.ClassConstant}, 668 {Attr: dwarf.AttrType, Val: dwarf.Offset(0xb7f), Class: dwarf.ClassReference}, 669 {Attr: dwarf.AttrDataMemberLoc, Val: []byte{0x23, 0x0}, Class: dwarf.ClassExprLoc}, 670 }, 671 }, 672 }, 673 { 674 entryNumber: 204, 675 entry: &dwarf.Entry{ 676 Offset: 0xc70, 677 Tag: dwarf.TagMember, 678 Children: false, 679 Field: []dwarf.Field{ 680 {Attr: dwarf.AttrName, Val: "it_value", Class: dwarf.ClassString}, 681 {Attr: dwarf.AttrDeclFile, Val: int64(7), Class: dwarf.ClassConstant}, 682 {Attr: dwarf.AttrDeclLine, Val: int64(237), Class: dwarf.ClassConstant}, 683 {Attr: dwarf.AttrType, Val: dwarf.Offset(0xb7f), Class: dwarf.ClassReference}, 684 {Attr: dwarf.AttrDataMemberLoc, Val: []byte{0x23, 0x10}, Class: dwarf.ClassExprLoc}, 685 }, 686 }, 687 }, 688 }, 689 }, 690 { 691 "testdata/go-relocation-test-gcc930-ranges-no-rela-x86-64", 692 []relocationTestEntry{ 693 { 694 entry: &dwarf.Entry{ 695 Offset: 0xb, 696 Tag: dwarf.TagCompileUnit, 697 Children: true, 698 Field: []dwarf.Field{ 699 {Attr: dwarf.AttrProducer, Val: "GNU C17 9.3.0 -mtune=generic -march=x86-64 -g -fno-asynchronous-unwind-tables", Class: dwarf.ClassString}, 700 {Attr: dwarf.AttrLanguage, Val: int64(12), Class: dwarf.ClassConstant}, 701 {Attr: dwarf.AttrName, Val: "multiple-code-sections.c", Class: dwarf.ClassString}, 702 {Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString}, 703 {Attr: dwarf.AttrRanges, Val: int64(0), Class: dwarf.ClassRangeListPtr}, 704 {Attr: dwarf.AttrLowpc, Val: uint64(0), Class: dwarf.ClassAddress}, 705 {Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr}, 706 }, 707 }, 708 pcRanges: [][2]uint64{ 709 {0x765, 0x777}, 710 {0x7e1, 0x7ec}, 711 }, 712 }, 713 }, 714 }, 715 { 716 "testdata/go-relocation-test-gcc930-ranges-with-rela-x86-64", 717 []relocationTestEntry{ 718 { 719 entry: &dwarf.Entry{ 720 Offset: 0xb, 721 Tag: dwarf.TagCompileUnit, 722 Children: true, 723 Field: []dwarf.Field{ 724 {Attr: dwarf.AttrProducer, Val: "GNU C17 9.3.0 -mtune=generic -march=x86-64 -g -fno-asynchronous-unwind-tables", Class: dwarf.ClassString}, 725 {Attr: dwarf.AttrLanguage, Val: int64(12), Class: dwarf.ClassConstant}, 726 {Attr: dwarf.AttrName, Val: "multiple-code-sections.c", Class: dwarf.ClassString}, 727 {Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString}, 728 {Attr: dwarf.AttrRanges, Val: int64(0), Class: dwarf.ClassRangeListPtr}, 729 {Attr: dwarf.AttrLowpc, Val: uint64(0), Class: dwarf.ClassAddress}, 730 {Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr}, 731 }, 732 }, 733 pcRanges: [][2]uint64{ 734 {0x765, 0x777}, 735 {0x7e1, 0x7ec}, 736 }, 737 }, 738 }, 739 }, 740 } 741 742 func TestDWARFRelocations(t *testing.T) { 743 for _, test := range relocationTests { 744 test := test 745 t.Run(test.file, func(t *testing.T) { 746 t.Parallel() 747 f, err := Open(test.file) 748 if err != nil { 749 t.Fatal(err) 750 } 751 dwarf, err := f.DWARF() 752 if err != nil { 753 t.Fatal(err) 754 } 755 reader := dwarf.Reader() 756 idx := 0 757 for _, testEntry := range test.entries { 758 if testEntry.entryNumber < idx { 759 t.Fatalf("internal test error: %d < %d", testEntry.entryNumber, idx) 760 } 761 for ; idx < testEntry.entryNumber; idx++ { 762 entry, err := reader.Next() 763 if entry == nil || err != nil { 764 t.Fatalf("Failed to skip to entry %d: %v", testEntry.entryNumber, err) 765 } 766 } 767 entry, err := reader.Next() 768 idx++ 769 if err != nil { 770 t.Fatal(err) 771 } 772 if !reflect.DeepEqual(testEntry.entry, entry) { 773 t.Errorf("entry %d mismatch: got:%#v want:%#v", testEntry.entryNumber, entry, testEntry.entry) 774 } 775 pcRanges, err := dwarf.Ranges(entry) 776 if err != nil { 777 t.Fatal(err) 778 } 779 if !reflect.DeepEqual(testEntry.pcRanges, pcRanges) { 780 t.Errorf("entry %d: PC range mismatch: got:%#v want:%#v", testEntry.entryNumber, pcRanges, testEntry.pcRanges) 781 } 782 } 783 }) 784 } 785 } 786 787 func TestCompressedDWARF(t *testing.T) { 788 // Test file built with GCC 4.8.4 and as 2.24 using: 789 // gcc -Wa,--compress-debug-sections -g -c -o zdebug-test-gcc484-x86-64.obj hello.c 790 f, err := Open("testdata/zdebug-test-gcc484-x86-64.obj") 791 if err != nil { 792 t.Fatal(err) 793 } 794 dwarf, err := f.DWARF() 795 if err != nil { 796 t.Fatal(err) 797 } 798 reader := dwarf.Reader() 799 n := 0 800 for { 801 entry, err := reader.Next() 802 if err != nil { 803 t.Fatal(err) 804 } 805 if entry == nil { 806 break 807 } 808 n++ 809 } 810 if n != 18 { 811 t.Fatalf("want %d DWARF entries, got %d", 18, n) 812 } 813 } 814 815 func TestCompressedSection(t *testing.T) { 816 // Test files built with gcc -g -S hello.c and assembled with 817 // --compress-debug-sections=zlib-gabi. 818 f, err := Open("testdata/compressed-64.obj") 819 if err != nil { 820 t.Fatal(err) 821 } 822 sec := f.Section(".debug_info") 823 wantData := []byte{ 824 182, 0, 0, 0, 4, 0, 0, 0, 0, 0, 8, 1, 0, 0, 0, 0, 825 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 826 0, 27, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 8, 7, 827 0, 0, 0, 0, 2, 1, 8, 0, 0, 0, 0, 2, 2, 7, 0, 0, 828 0, 0, 2, 4, 7, 0, 0, 0, 0, 2, 1, 6, 0, 0, 0, 0, 829 2, 2, 5, 0, 0, 0, 0, 3, 4, 5, 105, 110, 116, 0, 2, 8, 830 5, 0, 0, 0, 0, 2, 8, 7, 0, 0, 0, 0, 4, 8, 114, 0, 831 0, 0, 2, 1, 6, 0, 0, 0, 0, 5, 0, 0, 0, 0, 1, 4, 832 0, 0, 0, 0, 0, 0, 0, 0, 27, 0, 0, 0, 0, 0, 0, 0, 833 1, 156, 179, 0, 0, 0, 6, 0, 0, 0, 0, 1, 4, 87, 0, 0, 834 0, 2, 145, 108, 6, 0, 0, 0, 0, 1, 4, 179, 0, 0, 0, 2, 835 145, 96, 0, 4, 8, 108, 0, 0, 0, 0, 836 } 837 838 // Test Data method. 839 b, err := sec.Data() 840 if err != nil { 841 t.Fatal(err) 842 } 843 if !bytes.Equal(wantData, b) { 844 t.Fatalf("want data %x, got %x", wantData, b) 845 } 846 847 // Test Open method and seeking. 848 buf, have, count := make([]byte, len(b)), make([]bool, len(b)), 0 849 sf := sec.Open() 850 if got, err := sf.Seek(0, io.SeekEnd); got != int64(len(b)) || err != nil { 851 t.Fatalf("want seek end %d, got %d error %v", len(b), got, err) 852 } 853 if n, err := sf.Read(buf); n != 0 || err != io.EOF { 854 t.Fatalf("want EOF with 0 bytes, got %v with %d bytes", err, n) 855 } 856 pos := int64(len(buf)) 857 for count < len(buf) { 858 // Construct random seek arguments. 859 whence := rand.Intn(3) 860 target := rand.Int63n(int64(len(buf))) 861 var offset int64 862 switch whence { 863 case io.SeekStart: 864 offset = target 865 case io.SeekCurrent: 866 offset = target - pos 867 case io.SeekEnd: 868 offset = target - int64(len(buf)) 869 } 870 pos, err = sf.Seek(offset, whence) 871 if err != nil { 872 t.Fatal(err) 873 } 874 if pos != target { 875 t.Fatalf("want position %d, got %d", target, pos) 876 } 877 878 // Read data from the new position. 879 end := pos + 16 880 if end > int64(len(buf)) { 881 end = int64(len(buf)) 882 } 883 n, err := io.ReadFull(sf, buf[pos:end]) 884 if err != nil { 885 t.Fatal(err) 886 } 887 for i := 0; i < n; i++ { 888 if !have[pos] { 889 have[pos] = true 890 count++ 891 } 892 pos++ 893 } 894 } 895 if !bytes.Equal(wantData, buf) { 896 t.Fatalf("want data %x, got %x", wantData, buf) 897 } 898 } 899 900 func TestNoSectionOverlaps(t *testing.T) { 901 // Ensure cmd/link outputs sections without overlaps. 902 switch runtime.GOOS { 903 case "aix", "android", "darwin", "ios", "js", "plan9", "windows": 904 t.Skipf("cmd/link doesn't produce ELF binaries on %s", runtime.GOOS) 905 } 906 _ = net.ResolveIPAddr // force dynamic linkage 907 f, err := Open(os.Args[0]) 908 if err != nil { 909 t.Error(err) 910 return 911 } 912 for i, si := range f.Sections { 913 sih := si.SectionHeader 914 if sih.Type == SHT_NOBITS { 915 continue 916 } 917 // checking for overlap in file 918 for j, sj := range f.Sections { 919 sjh := sj.SectionHeader 920 if i == j || sjh.Type == SHT_NOBITS || sih.Offset == sjh.Offset && sih.FileSize == 0 { 921 continue 922 } 923 if sih.Offset >= sjh.Offset && sih.Offset < sjh.Offset+sjh.FileSize { 924 t.Errorf("ld produced ELF with section offset %s within %s: 0x%x <= 0x%x..0x%x < 0x%x", 925 sih.Name, sjh.Name, sjh.Offset, sih.Offset, sih.Offset+sih.FileSize, sjh.Offset+sjh.FileSize) 926 } 927 } 928 929 if sih.Flags&SHF_ALLOC == 0 { 930 continue 931 } 932 933 // checking for overlap in address space 934 for j, sj := range f.Sections { 935 sjh := sj.SectionHeader 936 if i == j || sjh.Flags&SHF_ALLOC == 0 || sjh.Type == SHT_NOBITS || 937 sih.Addr == sjh.Addr && sih.Size == 0 { 938 continue 939 } 940 if sih.Addr >= sjh.Addr && sih.Addr < sjh.Addr+sjh.Size { 941 t.Errorf("ld produced ELF with section address %s within %s: 0x%x <= 0x%x..0x%x < 0x%x", 942 sih.Name, sjh.Name, sjh.Addr, sih.Addr, sih.Addr+sih.Size, sjh.Addr+sjh.Size) 943 } 944 } 945 } 946 } 947 948 func TestNobitsSection(t *testing.T) { 949 const testdata = "testdata/gcc-amd64-linux-exec" 950 f, err := Open(testdata) 951 if err != nil { 952 t.Fatalf("could not read %s: %v", testdata, err) 953 } 954 defer f.Close() 955 956 wantError := "unexpected read from SHT_NOBITS section" 957 bss := f.Section(".bss") 958 959 _, err = bss.Data() 960 if err == nil || err.Error() != wantError { 961 t.Fatalf("bss.Data() got error %q, want error %q", err, wantError) 962 } 963 964 r := bss.Open() 965 p := make([]byte, 1) 966 _, err = r.Read(p) 967 if err == nil || err.Error() != wantError { 968 t.Fatalf("r.Read(p) got error %q, want error %q", err, wantError) 969 } 970 } 971 972 // TestLargeNumberOfSections tests the case that a file has greater than or 973 // equal to 65280 (0xff00) sections. 974 func TestLargeNumberOfSections(t *testing.T) { 975 // A file with >= 0xff00 sections is too big, so we will construct it on the 976 // fly. The original file "y.o" is generated by these commands: 977 // 1. generate "y.c": 978 // for i in `seq 1 65288`; do 979 // printf -v x "%04x" i; 980 // echo "int var_$x __attribute__((section(\"section_$x\"))) = $i;" 981 // done > y.c 982 // 2. compile: gcc -c y.c -m32 983 // 984 // $readelf -h y.o 985 // ELF Header: 986 // Magic: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00 987 // Class: ELF32 988 // Data: 2's complement, little endian 989 // Version: 1 (current) 990 // OS/ABI: UNIX - System V 991 // ABI Version: 0 992 // Type: REL (Relocatable file) 993 // Machine: Intel 80386 994 // Version: 0x1 995 // Entry point address: 0x0 996 // Start of program headers: 0 (bytes into file) 997 // Start of section headers: 3003468 (bytes into file) 998 // Flags: 0x0 999 // Size of this header: 52 (bytes) 1000 // Size of program headers: 0 (bytes) 1001 // Number of program headers: 0 1002 // Size of section headers: 40 (bytes) 1003 // Number of section headers: 0 (65298) 1004 // Section header string table index: 65535 (65297) 1005 // 1006 // $readelf -S y.o 1007 // There are 65298 section headers, starting at offset 0x2dd44c: 1008 // Section Headers: 1009 // [Nr] Name Type Addr Off Size ES Flg Lk Inf Al 1010 // [ 0] NULL 00000000 000000 00ff12 00 65297 0 0 1011 // [ 1] .text PROGBITS 00000000 000034 000000 00 AX 0 0 1 1012 // [ 2] .data PROGBITS 00000000 000034 000000 00 WA 0 0 1 1013 // [ 3] .bss NOBITS 00000000 000034 000000 00 WA 0 0 1 1014 // [ 4] section_0001 PROGBITS 00000000 000034 000004 00 WA 0 0 4 1015 // [ 5] section_0002 PROGBITS 00000000 000038 000004 00 WA 0 0 4 1016 // [ section_0003 ~ section_ff06 truncated ] 1017 // [65290] section_ff07 PROGBITS 00000000 03fc4c 000004 00 WA 0 0 4 1018 // [65291] section_ff08 PROGBITS 00000000 03fc50 000004 00 WA 0 0 4 1019 // [65292] .comment PROGBITS 00000000 03fc54 000027 01 MS 0 0 1 1020 // [65293] .note.GNU-stack PROGBITS 00000000 03fc7b 000000 00 0 0 1 1021 // [65294] .symtab SYMTAB 00000000 03fc7c 0ff0a0 10 65296 2 4 1022 // [65295] .symtab_shndx SYMTAB SECTION 00000000 13ed1c 03fc28 04 65294 0 4 1023 // [65296] .strtab STRTAB 00000000 17e944 08f74d 00 0 0 1 1024 // [65297] .shstrtab STRTAB 00000000 20e091 0cf3bb 00 0 0 1 1025 1026 var buf bytes.Buffer 1027 1028 { 1029 buf.Grow(0x55AF1C) // 3003468 + 40 * 65298 1030 1031 h := Header32{ 1032 Ident: [16]byte{0x7F, 'E', 'L', 'F', 0x01, 0x01, 0x01}, 1033 Type: 1, 1034 Machine: 3, 1035 Version: 1, 1036 Shoff: 0x2DD44C, 1037 Ehsize: 0x34, 1038 Shentsize: 0x28, 1039 Shnum: 0, 1040 Shstrndx: 0xFFFF, 1041 } 1042 binary.Write(&buf, binary.LittleEndian, h) 1043 1044 // Zero out sections [1]~[65294]. 1045 buf.Write(bytes.Repeat([]byte{0}, 0x13ED1C-binary.Size(h))) 1046 1047 // Write section [65295]. Section [65295] are all zeros except for the 1048 // last 48 bytes. 1049 buf.Write(bytes.Repeat([]byte{0}, 0x03FC28-12*4)) 1050 for i := 0; i < 12; i++ { 1051 binary.Write(&buf, binary.LittleEndian, uint32(0xFF00|i)) 1052 } 1053 1054 // Write section [65296]. 1055 buf.Write([]byte{0}) 1056 buf.Write([]byte("y.c\x00")) 1057 for i := 1; i <= 65288; i++ { 1058 // var_0001 ~ var_ff08 1059 name := fmt.Sprintf("var_%04x", i) 1060 buf.Write([]byte(name)) 1061 buf.Write([]byte{0}) 1062 } 1063 1064 // Write section [65297]. 1065 buf.Write([]byte{0}) 1066 buf.Write([]byte(".symtab\x00")) 1067 buf.Write([]byte(".strtab\x00")) 1068 buf.Write([]byte(".shstrtab\x00")) 1069 buf.Write([]byte(".text\x00")) 1070 buf.Write([]byte(".data\x00")) 1071 buf.Write([]byte(".bss\x00")) 1072 for i := 1; i <= 65288; i++ { 1073 // s_0001 ~ s_ff08 1074 name := fmt.Sprintf("section_%04x", i) 1075 buf.Write([]byte(name)) 1076 buf.Write([]byte{0}) 1077 } 1078 buf.Write([]byte(".comment\x00")) 1079 buf.Write([]byte(".note.GNU-stack\x00")) 1080 buf.Write([]byte(".symtab_shndx\x00")) 1081 1082 // Write section header table. 1083 // NULL 1084 binary.Write(&buf, binary.LittleEndian, Section32{Name: 0, Size: 0xFF12, Link: 0xFF11}) 1085 // .text 1086 binary.Write(&buf, binary.LittleEndian, Section32{ 1087 Name: 0x1B, 1088 Type: uint32(SHT_PROGBITS), 1089 Flags: uint32(uint32(SHF_ALLOC | SHF_EXECINSTR)), 1090 Off: 0x34, 1091 Addralign: 0x01, 1092 }) 1093 // .data 1094 binary.Write(&buf, binary.LittleEndian, Section32{ 1095 Name: 0x21, 1096 Type: uint32(SHT_PROGBITS), 1097 Flags: uint32(SHF_WRITE | SHF_ALLOC), 1098 Off: 0x34, 1099 Addralign: 0x01, 1100 }) 1101 // .bss 1102 binary.Write(&buf, binary.LittleEndian, Section32{ 1103 Name: 0x27, 1104 Type: uint32(SHT_NOBITS), 1105 Flags: uint32(SHF_WRITE | SHF_ALLOC), 1106 Off: 0x34, 1107 Addralign: 0x01, 1108 }) 1109 // s_1 ~ s_65537 1110 for i := 0; i < 65288; i++ { 1111 s := Section32{ 1112 Name: uint32(0x2C + i*13), 1113 Type: uint32(SHT_PROGBITS), 1114 Flags: uint32(SHF_WRITE | SHF_ALLOC), 1115 Off: uint32(0x34 + i*4), 1116 Size: 0x04, 1117 Addralign: 0x04, 1118 } 1119 binary.Write(&buf, binary.LittleEndian, s) 1120 } 1121 // .comment 1122 binary.Write(&buf, binary.LittleEndian, Section32{ 1123 Name: 0x0CF394, 1124 Type: uint32(SHT_PROGBITS), 1125 Flags: uint32(SHF_MERGE | SHF_STRINGS), 1126 Off: 0x03FC54, 1127 Size: 0x27, 1128 Addralign: 0x01, 1129 Entsize: 0x01, 1130 }) 1131 // .note.GNU-stack 1132 binary.Write(&buf, binary.LittleEndian, Section32{ 1133 Name: 0x0CF39D, 1134 Type: uint32(SHT_PROGBITS), 1135 Off: 0x03FC7B, 1136 Addralign: 0x01, 1137 }) 1138 // .symtab 1139 binary.Write(&buf, binary.LittleEndian, Section32{ 1140 Name: 0x01, 1141 Type: uint32(SHT_SYMTAB), 1142 Off: 0x03FC7C, 1143 Size: 0x0FF0A0, 1144 Link: 0xFF10, 1145 Info: 0x02, 1146 Addralign: 0x04, 1147 Entsize: 0x10, 1148 }) 1149 // .symtab_shndx 1150 binary.Write(&buf, binary.LittleEndian, Section32{ 1151 Name: 0x0CF3AD, 1152 Type: uint32(SHT_SYMTAB_SHNDX), 1153 Off: 0x13ED1C, 1154 Size: 0x03FC28, 1155 Link: 0xFF0E, 1156 Addralign: 0x04, 1157 Entsize: 0x04, 1158 }) 1159 // .strtab 1160 binary.Write(&buf, binary.LittleEndian, Section32{ 1161 Name: 0x09, 1162 Type: uint32(SHT_STRTAB), 1163 Off: 0x17E944, 1164 Size: 0x08F74D, 1165 Addralign: 0x01, 1166 }) 1167 // .shstrtab 1168 binary.Write(&buf, binary.LittleEndian, Section32{ 1169 Name: 0x11, 1170 Type: uint32(SHT_STRTAB), 1171 Off: 0x20E091, 1172 Size: 0x0CF3BB, 1173 Addralign: 0x01, 1174 }) 1175 } 1176 1177 data := buf.Bytes() 1178 1179 f, err := NewFile(bytes.NewReader(data)) 1180 if err != nil { 1181 t.Errorf("cannot create file from data: %v", err) 1182 } 1183 defer f.Close() 1184 1185 wantFileHeader := FileHeader{ 1186 Class: ELFCLASS32, 1187 Data: ELFDATA2LSB, 1188 Version: EV_CURRENT, 1189 OSABI: ELFOSABI_NONE, 1190 ByteOrder: binary.LittleEndian, 1191 Type: ET_REL, 1192 Machine: EM_386, 1193 } 1194 if f.FileHeader != wantFileHeader { 1195 t.Errorf("\nhave %#v\nwant %#v\n", f.FileHeader, wantFileHeader) 1196 } 1197 1198 wantSectionNum := 65298 1199 if len(f.Sections) != wantSectionNum { 1200 t.Errorf("len(Sections) = %d, want %d", len(f.Sections), wantSectionNum) 1201 } 1202 1203 wantSectionHeader := SectionHeader{ 1204 Name: "section_0007", 1205 Type: SHT_PROGBITS, 1206 Flags: SHF_WRITE + SHF_ALLOC, 1207 Offset: 0x4c, 1208 Size: 0x4, 1209 Addralign: 0x4, 1210 FileSize: 0x4, 1211 } 1212 if f.Sections[10].SectionHeader != wantSectionHeader { 1213 t.Errorf("\nhave %#v\nwant %#v\n", f.Sections[10].SectionHeader, wantSectionHeader) 1214 } 1215 } 1216 1217 func TestIssue10996(t *testing.T) { 1218 data := []byte("\u007fELF\x02\x01\x010000000000000" + 1219 "\x010000000000000000000" + 1220 "\x00\x00\x00\x00\x00\x00\x00\x0000000000\x00\x00\x00\x00" + 1221 "0000") 1222 _, err := NewFile(bytes.NewReader(data)) 1223 if err == nil { 1224 t.Fatalf("opening invalid ELF file unexpectedly succeeded") 1225 } 1226 }