github.com/comwrg/go/src@v0.0.0-20220319063731-c238d0440370/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 "io" 13 "math/rand" 14 "net" 15 "os" 16 "path" 17 "reflect" 18 "runtime" 19 "testing" 20 ) 21 22 type fileTest struct { 23 file string 24 hdr FileHeader 25 sections []SectionHeader 26 progs []ProgHeader 27 needed []string 28 } 29 30 var fileTests = []fileTest{ 31 { 32 "testdata/gcc-386-freebsd-exec", 33 FileHeader{ELFCLASS32, ELFDATA2LSB, EV_CURRENT, ELFOSABI_FREEBSD, 0, binary.LittleEndian, ET_EXEC, EM_386, 0x80483cc}, 34 []SectionHeader{ 35 {"", SHT_NULL, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, 36 {".interp", SHT_PROGBITS, SHF_ALLOC, 0x80480d4, 0xd4, 0x15, 0x0, 0x0, 0x1, 0x0, 0x15}, 37 {".hash", SHT_HASH, SHF_ALLOC, 0x80480ec, 0xec, 0x90, 0x3, 0x0, 0x4, 0x4, 0x90}, 38 {".dynsym", SHT_DYNSYM, SHF_ALLOC, 0x804817c, 0x17c, 0x110, 0x4, 0x1, 0x4, 0x10, 0x110}, 39 {".dynstr", SHT_STRTAB, SHF_ALLOC, 0x804828c, 0x28c, 0xbb, 0x0, 0x0, 0x1, 0x0, 0xbb}, 40 {".rel.plt", SHT_REL, SHF_ALLOC, 0x8048348, 0x348, 0x20, 0x3, 0x7, 0x4, 0x8, 0x20}, 41 {".init", SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR, 0x8048368, 0x368, 0x11, 0x0, 0x0, 0x4, 0x0, 0x11}, 42 {".plt", SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR, 0x804837c, 0x37c, 0x50, 0x0, 0x0, 0x4, 0x4, 0x50}, 43 {".text", SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR, 0x80483cc, 0x3cc, 0x180, 0x0, 0x0, 0x4, 0x0, 0x180}, 44 {".fini", SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR, 0x804854c, 0x54c, 0xc, 0x0, 0x0, 0x4, 0x0, 0xc}, 45 {".rodata", SHT_PROGBITS, SHF_ALLOC, 0x8048558, 0x558, 0xa3, 0x0, 0x0, 0x1, 0x0, 0xa3}, 46 {".data", SHT_PROGBITS, SHF_WRITE + SHF_ALLOC, 0x80495fc, 0x5fc, 0xc, 0x0, 0x0, 0x4, 0x0, 0xc}, 47 {".eh_frame", SHT_PROGBITS, SHF_ALLOC, 0x8049608, 0x608, 0x4, 0x0, 0x0, 0x4, 0x0, 0x4}, 48 {".dynamic", SHT_DYNAMIC, SHF_WRITE + SHF_ALLOC, 0x804960c, 0x60c, 0x98, 0x4, 0x0, 0x4, 0x8, 0x98}, 49 {".ctors", SHT_PROGBITS, SHF_WRITE + SHF_ALLOC, 0x80496a4, 0x6a4, 0x8, 0x0, 0x0, 0x4, 0x0, 0x8}, 50 {".dtors", SHT_PROGBITS, SHF_WRITE + SHF_ALLOC, 0x80496ac, 0x6ac, 0x8, 0x0, 0x0, 0x4, 0x0, 0x8}, 51 {".jcr", SHT_PROGBITS, SHF_WRITE + SHF_ALLOC, 0x80496b4, 0x6b4, 0x4, 0x0, 0x0, 0x4, 0x0, 0x4}, 52 {".got", SHT_PROGBITS, SHF_WRITE + SHF_ALLOC, 0x80496b8, 0x6b8, 0x1c, 0x0, 0x0, 0x4, 0x4, 0x1c}, 53 {".bss", SHT_NOBITS, SHF_WRITE + SHF_ALLOC, 0x80496d4, 0x6d4, 0x20, 0x0, 0x0, 0x4, 0x0, 0x20}, 54 {".comment", SHT_PROGBITS, 0x0, 0x0, 0x6d4, 0x12d, 0x0, 0x0, 0x1, 0x0, 0x12d}, 55 {".debug_aranges", SHT_PROGBITS, 0x0, 0x0, 0x801, 0x20, 0x0, 0x0, 0x1, 0x0, 0x20}, 56 {".debug_pubnames", SHT_PROGBITS, 0x0, 0x0, 0x821, 0x1b, 0x0, 0x0, 0x1, 0x0, 0x1b}, 57 {".debug_info", SHT_PROGBITS, 0x0, 0x0, 0x83c, 0x11d, 0x0, 0x0, 0x1, 0x0, 0x11d}, 58 {".debug_abbrev", SHT_PROGBITS, 0x0, 0x0, 0x959, 0x41, 0x0, 0x0, 0x1, 0x0, 0x41}, 59 {".debug_line", SHT_PROGBITS, 0x0, 0x0, 0x99a, 0x35, 0x0, 0x0, 0x1, 0x0, 0x35}, 60 {".debug_frame", SHT_PROGBITS, 0x0, 0x0, 0x9d0, 0x30, 0x0, 0x0, 0x4, 0x0, 0x30}, 61 {".debug_str", SHT_PROGBITS, 0x0, 0x0, 0xa00, 0xd, 0x0, 0x0, 0x1, 0x0, 0xd}, 62 {".shstrtab", SHT_STRTAB, 0x0, 0x0, 0xa0d, 0xf8, 0x0, 0x0, 0x1, 0x0, 0xf8}, 63 {".symtab", SHT_SYMTAB, 0x0, 0x0, 0xfb8, 0x4b0, 0x1d, 0x38, 0x4, 0x10, 0x4b0}, 64 {".strtab", SHT_STRTAB, 0x0, 0x0, 0x1468, 0x206, 0x0, 0x0, 0x1, 0x0, 0x206}, 65 }, 66 []ProgHeader{ 67 {PT_PHDR, PF_R + PF_X, 0x34, 0x8048034, 0x8048034, 0xa0, 0xa0, 0x4}, 68 {PT_INTERP, PF_R, 0xd4, 0x80480d4, 0x80480d4, 0x15, 0x15, 0x1}, 69 {PT_LOAD, PF_R + PF_X, 0x0, 0x8048000, 0x8048000, 0x5fb, 0x5fb, 0x1000}, 70 {PT_LOAD, PF_R + PF_W, 0x5fc, 0x80495fc, 0x80495fc, 0xd8, 0xf8, 0x1000}, 71 {PT_DYNAMIC, PF_R + PF_W, 0x60c, 0x804960c, 0x804960c, 0x98, 0x98, 0x4}, 72 }, 73 []string{"libc.so.6"}, 74 }, 75 { 76 "testdata/gcc-amd64-linux-exec", 77 FileHeader{ELFCLASS64, ELFDATA2LSB, EV_CURRENT, ELFOSABI_NONE, 0, binary.LittleEndian, ET_EXEC, EM_X86_64, 0x4003e0}, 78 []SectionHeader{ 79 {"", SHT_NULL, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, 80 {".interp", SHT_PROGBITS, SHF_ALLOC, 0x400200, 0x200, 0x1c, 0x0, 0x0, 0x1, 0x0, 0x1c}, 81 {".note.ABI-tag", SHT_NOTE, SHF_ALLOC, 0x40021c, 0x21c, 0x20, 0x0, 0x0, 0x4, 0x0, 0x20}, 82 {".hash", SHT_HASH, SHF_ALLOC, 0x400240, 0x240, 0x24, 0x5, 0x0, 0x8, 0x4, 0x24}, 83 {".gnu.hash", SHT_LOOS + 268435446, SHF_ALLOC, 0x400268, 0x268, 0x1c, 0x5, 0x0, 0x8, 0x0, 0x1c}, 84 {".dynsym", SHT_DYNSYM, SHF_ALLOC, 0x400288, 0x288, 0x60, 0x6, 0x1, 0x8, 0x18, 0x60}, 85 {".dynstr", SHT_STRTAB, SHF_ALLOC, 0x4002e8, 0x2e8, 0x3d, 0x0, 0x0, 0x1, 0x0, 0x3d}, 86 {".gnu.version", SHT_HIOS, SHF_ALLOC, 0x400326, 0x326, 0x8, 0x5, 0x0, 0x2, 0x2, 0x8}, 87 {".gnu.version_r", SHT_LOOS + 268435454, SHF_ALLOC, 0x400330, 0x330, 0x20, 0x6, 0x1, 0x8, 0x0, 0x20}, 88 {".rela.dyn", SHT_RELA, SHF_ALLOC, 0x400350, 0x350, 0x18, 0x5, 0x0, 0x8, 0x18, 0x18}, 89 {".rela.plt", SHT_RELA, SHF_ALLOC, 0x400368, 0x368, 0x30, 0x5, 0xc, 0x8, 0x18, 0x30}, 90 {".init", SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR, 0x400398, 0x398, 0x18, 0x0, 0x0, 0x4, 0x0, 0x18}, 91 {".plt", SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR, 0x4003b0, 0x3b0, 0x30, 0x0, 0x0, 0x4, 0x10, 0x30}, 92 {".text", SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR, 0x4003e0, 0x3e0, 0x1b4, 0x0, 0x0, 0x10, 0x0, 0x1b4}, 93 {".fini", SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR, 0x400594, 0x594, 0xe, 0x0, 0x0, 0x4, 0x0, 0xe}, 94 {".rodata", SHT_PROGBITS, SHF_ALLOC, 0x4005a4, 0x5a4, 0x11, 0x0, 0x0, 0x4, 0x0, 0x11}, 95 {".eh_frame_hdr", SHT_PROGBITS, SHF_ALLOC, 0x4005b8, 0x5b8, 0x24, 0x0, 0x0, 0x4, 0x0, 0x24}, 96 {".eh_frame", SHT_PROGBITS, SHF_ALLOC, 0x4005e0, 0x5e0, 0xa4, 0x0, 0x0, 0x8, 0x0, 0xa4}, 97 {".ctors", SHT_PROGBITS, SHF_WRITE + SHF_ALLOC, 0x600688, 0x688, 0x10, 0x0, 0x0, 0x8, 0x0, 0x10}, 98 {".dtors", SHT_PROGBITS, SHF_WRITE + SHF_ALLOC, 0x600698, 0x698, 0x10, 0x0, 0x0, 0x8, 0x0, 0x10}, 99 {".jcr", SHT_PROGBITS, SHF_WRITE + SHF_ALLOC, 0x6006a8, 0x6a8, 0x8, 0x0, 0x0, 0x8, 0x0, 0x8}, 100 {".dynamic", SHT_DYNAMIC, SHF_WRITE + SHF_ALLOC, 0x6006b0, 0x6b0, 0x1a0, 0x6, 0x0, 0x8, 0x10, 0x1a0}, 101 {".got", SHT_PROGBITS, SHF_WRITE + SHF_ALLOC, 0x600850, 0x850, 0x8, 0x0, 0x0, 0x8, 0x8, 0x8}, 102 {".got.plt", SHT_PROGBITS, SHF_WRITE + SHF_ALLOC, 0x600858, 0x858, 0x28, 0x0, 0x0, 0x8, 0x8, 0x28}, 103 {".data", SHT_PROGBITS, SHF_WRITE + SHF_ALLOC, 0x600880, 0x880, 0x18, 0x0, 0x0, 0x8, 0x0, 0x18}, 104 {".bss", SHT_NOBITS, SHF_WRITE + SHF_ALLOC, 0x600898, 0x898, 0x8, 0x0, 0x0, 0x4, 0x0, 0x8}, 105 {".comment", SHT_PROGBITS, 0x0, 0x0, 0x898, 0x126, 0x0, 0x0, 0x1, 0x0, 0x126}, 106 {".debug_aranges", SHT_PROGBITS, 0x0, 0x0, 0x9c0, 0x90, 0x0, 0x0, 0x10, 0x0, 0x90}, 107 {".debug_pubnames", SHT_PROGBITS, 0x0, 0x0, 0xa50, 0x25, 0x0, 0x0, 0x1, 0x0, 0x25}, 108 {".debug_info", SHT_PROGBITS, 0x0, 0x0, 0xa75, 0x1a7, 0x0, 0x0, 0x1, 0x0, 0x1a7}, 109 {".debug_abbrev", SHT_PROGBITS, 0x0, 0x0, 0xc1c, 0x6f, 0x0, 0x0, 0x1, 0x0, 0x6f}, 110 {".debug_line", SHT_PROGBITS, 0x0, 0x0, 0xc8b, 0x13f, 0x0, 0x0, 0x1, 0x0, 0x13f}, 111 {".debug_str", SHT_PROGBITS, SHF_MERGE + SHF_STRINGS, 0x0, 0xdca, 0xb1, 0x0, 0x0, 0x1, 0x1, 0xb1}, 112 {".debug_ranges", SHT_PROGBITS, 0x0, 0x0, 0xe80, 0x90, 0x0, 0x0, 0x10, 0x0, 0x90}, 113 {".shstrtab", SHT_STRTAB, 0x0, 0x0, 0xf10, 0x149, 0x0, 0x0, 0x1, 0x0, 0x149}, 114 {".symtab", SHT_SYMTAB, 0x0, 0x0, 0x19a0, 0x6f0, 0x24, 0x39, 0x8, 0x18, 0x6f0}, 115 {".strtab", SHT_STRTAB, 0x0, 0x0, 0x2090, 0x1fc, 0x0, 0x0, 0x1, 0x0, 0x1fc}, 116 }, 117 []ProgHeader{ 118 {PT_PHDR, PF_R + PF_X, 0x40, 0x400040, 0x400040, 0x1c0, 0x1c0, 0x8}, 119 {PT_INTERP, PF_R, 0x200, 0x400200, 0x400200, 0x1c, 0x1c, 1}, 120 {PT_LOAD, PF_R + PF_X, 0x0, 0x400000, 0x400000, 0x684, 0x684, 0x200000}, 121 {PT_LOAD, PF_R + PF_W, 0x688, 0x600688, 0x600688, 0x210, 0x218, 0x200000}, 122 {PT_DYNAMIC, PF_R + PF_W, 0x6b0, 0x6006b0, 0x6006b0, 0x1a0, 0x1a0, 0x8}, 123 {PT_NOTE, PF_R, 0x21c, 0x40021c, 0x40021c, 0x20, 0x20, 0x4}, 124 {PT_LOOS + 0x474E550, PF_R, 0x5b8, 0x4005b8, 0x4005b8, 0x24, 0x24, 0x4}, 125 {PT_LOOS + 0x474E551, PF_R + PF_W, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8}, 126 }, 127 []string{"libc.so.6"}, 128 }, 129 { 130 "testdata/hello-world-core.gz", 131 FileHeader{ELFCLASS64, ELFDATA2LSB, EV_CURRENT, ELFOSABI_NONE, 0x0, binary.LittleEndian, ET_CORE, EM_X86_64, 0x0}, 132 []SectionHeader{}, 133 []ProgHeader{ 134 {Type: PT_NOTE, Flags: 0x0, Off: 0x3f8, Vaddr: 0x0, Paddr: 0x0, Filesz: 0x8ac, Memsz: 0x0, Align: 0x0}, 135 {Type: PT_LOAD, Flags: PF_X + PF_R, Off: 0x1000, Vaddr: 0x400000, Paddr: 0x0, Filesz: 0x0, Memsz: 0x1000, Align: 0x1000}, 136 {Type: PT_LOAD, Flags: PF_R, Off: 0x1000, Vaddr: 0x401000, Paddr: 0x0, Filesz: 0x1000, Memsz: 0x1000, Align: 0x1000}, 137 {Type: PT_LOAD, Flags: PF_W + PF_R, Off: 0x2000, Vaddr: 0x402000, Paddr: 0x0, Filesz: 0x1000, Memsz: 0x1000, Align: 0x1000}, 138 {Type: PT_LOAD, Flags: PF_X + PF_R, Off: 0x3000, Vaddr: 0x7f54078b8000, Paddr: 0x0, Filesz: 0x0, Memsz: 0x1b5000, Align: 0x1000}, 139 {Type: PT_LOAD, Flags: 0x0, Off: 0x3000, Vaddr: 0x7f5407a6d000, Paddr: 0x0, Filesz: 0x0, Memsz: 0x1ff000, Align: 0x1000}, 140 {Type: PT_LOAD, Flags: PF_R, Off: 0x3000, Vaddr: 0x7f5407c6c000, Paddr: 0x0, Filesz: 0x4000, Memsz: 0x4000, Align: 0x1000}, 141 {Type: PT_LOAD, Flags: PF_W + PF_R, Off: 0x7000, Vaddr: 0x7f5407c70000, Paddr: 0x0, Filesz: 0x2000, Memsz: 0x2000, Align: 0x1000}, 142 {Type: PT_LOAD, Flags: PF_W + PF_R, Off: 0x9000, Vaddr: 0x7f5407c72000, Paddr: 0x0, Filesz: 0x5000, Memsz: 0x5000, Align: 0x1000}, 143 {Type: PT_LOAD, Flags: PF_X + PF_R, Off: 0xe000, Vaddr: 0x7f5407c77000, Paddr: 0x0, Filesz: 0x0, Memsz: 0x22000, Align: 0x1000}, 144 {Type: PT_LOAD, Flags: PF_W + PF_R, Off: 0xe000, Vaddr: 0x7f5407e81000, Paddr: 0x0, Filesz: 0x3000, Memsz: 0x3000, Align: 0x1000}, 145 {Type: PT_LOAD, Flags: PF_W + PF_R, Off: 0x11000, Vaddr: 0x7f5407e96000, Paddr: 0x0, Filesz: 0x3000, Memsz: 0x3000, Align: 0x1000}, 146 {Type: PT_LOAD, Flags: PF_R, Off: 0x14000, Vaddr: 0x7f5407e99000, Paddr: 0x0, Filesz: 0x1000, Memsz: 0x1000, Align: 0x1000}, 147 {Type: PT_LOAD, Flags: PF_W + PF_R, Off: 0x15000, Vaddr: 0x7f5407e9a000, Paddr: 0x0, Filesz: 0x2000, Memsz: 0x2000, Align: 0x1000}, 148 {Type: PT_LOAD, Flags: PF_W + PF_R, Off: 0x17000, Vaddr: 0x7fff79972000, Paddr: 0x0, Filesz: 0x23000, Memsz: 0x23000, Align: 0x1000}, 149 {Type: PT_LOAD, Flags: PF_X + PF_R, Off: 0x3a000, Vaddr: 0x7fff799f8000, Paddr: 0x0, Filesz: 0x1000, Memsz: 0x1000, Align: 0x1000}, 150 {Type: PT_LOAD, Flags: PF_X + PF_R, Off: 0x3b000, Vaddr: 0xffffffffff600000, Paddr: 0x0, Filesz: 0x1000, Memsz: 0x1000, Align: 0x1000}, 151 }, 152 nil, 153 }, 154 { 155 "testdata/compressed-32.obj", 156 FileHeader{ELFCLASS32, ELFDATA2LSB, EV_CURRENT, ELFOSABI_NONE, 0x0, binary.LittleEndian, ET_REL, EM_386, 0x0}, 157 []SectionHeader{ 158 {"", SHT_NULL, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, 159 {".text", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR, 0x0, 0x34, 0x17, 0x0, 0x0, 0x1, 0x0, 0x17}, 160 {".rel.text", SHT_REL, SHF_INFO_LINK, 0x0, 0x3dc, 0x10, 0x13, 0x1, 0x4, 0x8, 0x10}, 161 {".data", SHT_PROGBITS, SHF_WRITE | SHF_ALLOC, 0x0, 0x4b, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0}, 162 {".bss", SHT_NOBITS, SHF_WRITE | SHF_ALLOC, 0x0, 0x4b, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0}, 163 {".rodata", SHT_PROGBITS, SHF_ALLOC, 0x0, 0x4b, 0xd, 0x0, 0x0, 0x1, 0x0, 0xd}, 164 {".debug_info", SHT_PROGBITS, SHF_COMPRESSED, 0x0, 0x58, 0xb4, 0x0, 0x0, 0x1, 0x0, 0x84}, 165 {".rel.debug_info", SHT_REL, SHF_INFO_LINK, 0x0, 0x3ec, 0xa0, 0x13, 0x6, 0x4, 0x8, 0xa0}, 166 {".debug_abbrev", SHT_PROGBITS, 0x0, 0x0, 0xdc, 0x5a, 0x0, 0x0, 0x1, 0x0, 0x5a}, 167 {".debug_aranges", SHT_PROGBITS, 0x0, 0x0, 0x136, 0x20, 0x0, 0x0, 0x1, 0x0, 0x20}, 168 {".rel.debug_aranges", SHT_REL, SHF_INFO_LINK, 0x0, 0x48c, 0x10, 0x13, 0x9, 0x4, 0x8, 0x10}, 169 {".debug_line", SHT_PROGBITS, 0x0, 0x0, 0x156, 0x5c, 0x0, 0x0, 0x1, 0x0, 0x5c}, 170 {".rel.debug_line", SHT_REL, SHF_INFO_LINK, 0x0, 0x49c, 0x8, 0x13, 0xb, 0x4, 0x8, 0x8}, 171 {".debug_str", SHT_PROGBITS, SHF_MERGE | SHF_STRINGS | SHF_COMPRESSED, 0x0, 0x1b2, 0x10f, 0x0, 0x0, 0x1, 0x1, 0xb3}, 172 {".comment", SHT_PROGBITS, SHF_MERGE | SHF_STRINGS, 0x0, 0x265, 0x2a, 0x0, 0x0, 0x1, 0x1, 0x2a}, 173 {".note.GNU-stack", SHT_PROGBITS, 0x0, 0x0, 0x28f, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0}, 174 {".eh_frame", SHT_PROGBITS, SHF_ALLOC, 0x0, 0x290, 0x38, 0x0, 0x0, 0x4, 0x0, 0x38}, 175 {".rel.eh_frame", SHT_REL, SHF_INFO_LINK, 0x0, 0x4a4, 0x8, 0x13, 0x10, 0x4, 0x8, 0x8}, 176 {".shstrtab", SHT_STRTAB, 0x0, 0x0, 0x4ac, 0xab, 0x0, 0x0, 0x1, 0x0, 0xab}, 177 {".symtab", SHT_SYMTAB, 0x0, 0x0, 0x2c8, 0x100, 0x14, 0xe, 0x4, 0x10, 0x100}, 178 {".strtab", SHT_STRTAB, 0x0, 0x0, 0x3c8, 0x13, 0x0, 0x0, 0x1, 0x0, 0x13}, 179 }, 180 []ProgHeader{}, 181 nil, 182 }, 183 { 184 "testdata/compressed-64.obj", 185 FileHeader{ELFCLASS64, ELFDATA2LSB, EV_CURRENT, ELFOSABI_NONE, 0x0, binary.LittleEndian, ET_REL, EM_X86_64, 0x0}, 186 []SectionHeader{ 187 {"", SHT_NULL, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, 188 {".text", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR, 0x0, 0x40, 0x1b, 0x0, 0x0, 0x1, 0x0, 0x1b}, 189 {".rela.text", SHT_RELA, SHF_INFO_LINK, 0x0, 0x488, 0x30, 0x13, 0x1, 0x8, 0x18, 0x30}, 190 {".data", SHT_PROGBITS, SHF_WRITE | SHF_ALLOC, 0x0, 0x5b, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0}, 191 {".bss", SHT_NOBITS, SHF_WRITE | SHF_ALLOC, 0x0, 0x5b, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0}, 192 {".rodata", SHT_PROGBITS, SHF_ALLOC, 0x0, 0x5b, 0xd, 0x0, 0x0, 0x1, 0x0, 0xd}, 193 {".debug_info", SHT_PROGBITS, SHF_COMPRESSED, 0x0, 0x68, 0xba, 0x0, 0x0, 0x1, 0x0, 0x72}, 194 {".rela.debug_info", SHT_RELA, SHF_INFO_LINK, 0x0, 0x4b8, 0x1c8, 0x13, 0x6, 0x8, 0x18, 0x1c8}, 195 {".debug_abbrev", SHT_PROGBITS, 0x0, 0x0, 0xda, 0x5c, 0x0, 0x0, 0x1, 0x0, 0x5c}, 196 {".debug_aranges", SHT_PROGBITS, SHF_COMPRESSED, 0x0, 0x136, 0x30, 0x0, 0x0, 0x1, 0x0, 0x2f}, 197 {".rela.debug_aranges", SHT_RELA, SHF_INFO_LINK, 0x0, 0x680, 0x30, 0x13, 0x9, 0x8, 0x18, 0x30}, 198 {".debug_line", SHT_PROGBITS, 0x0, 0x0, 0x165, 0x60, 0x0, 0x0, 0x1, 0x0, 0x60}, 199 {".rela.debug_line", SHT_RELA, SHF_INFO_LINK, 0x0, 0x6b0, 0x18, 0x13, 0xb, 0x8, 0x18, 0x18}, 200 {".debug_str", SHT_PROGBITS, SHF_MERGE | SHF_STRINGS | SHF_COMPRESSED, 0x0, 0x1c5, 0x104, 0x0, 0x0, 0x1, 0x1, 0xc3}, 201 {".comment", SHT_PROGBITS, SHF_MERGE | SHF_STRINGS, 0x0, 0x288, 0x2a, 0x0, 0x0, 0x1, 0x1, 0x2a}, 202 {".note.GNU-stack", SHT_PROGBITS, 0x0, 0x0, 0x2b2, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0}, 203 {".eh_frame", SHT_PROGBITS, SHF_ALLOC, 0x0, 0x2b8, 0x38, 0x0, 0x0, 0x8, 0x0, 0x38}, 204 {".rela.eh_frame", SHT_RELA, SHF_INFO_LINK, 0x0, 0x6c8, 0x18, 0x13, 0x10, 0x8, 0x18, 0x18}, 205 {".shstrtab", SHT_STRTAB, 0x0, 0x0, 0x6e0, 0xb0, 0x0, 0x0, 0x1, 0x0, 0xb0}, 206 {".symtab", SHT_SYMTAB, 0x0, 0x0, 0x2f0, 0x180, 0x14, 0xe, 0x8, 0x18, 0x180}, 207 {".strtab", SHT_STRTAB, 0x0, 0x0, 0x470, 0x13, 0x0, 0x0, 0x1, 0x0, 0x13}, 208 }, 209 []ProgHeader{}, 210 nil, 211 }, 212 } 213 214 func TestOpen(t *testing.T) { 215 for i := range fileTests { 216 tt := &fileTests[i] 217 218 var f *File 219 var err error 220 if path.Ext(tt.file) == ".gz" { 221 var r io.ReaderAt 222 if r, err = decompress(tt.file); err == nil { 223 f, err = NewFile(r) 224 } 225 } else { 226 f, err = Open(tt.file) 227 } 228 if err != nil { 229 t.Errorf("cannot open file %s: %v", tt.file, err) 230 continue 231 } 232 defer f.Close() 233 if !reflect.DeepEqual(f.FileHeader, tt.hdr) { 234 t.Errorf("open %s:\n\thave %#v\n\twant %#v\n", tt.file, f.FileHeader, tt.hdr) 235 continue 236 } 237 for i, s := range f.Sections { 238 if i >= len(tt.sections) { 239 break 240 } 241 sh := &tt.sections[i] 242 if !reflect.DeepEqual(&s.SectionHeader, sh) { 243 t.Errorf("open %s, section %d:\n\thave %#v\n\twant %#v\n", tt.file, i, &s.SectionHeader, sh) 244 } 245 } 246 for i, p := range f.Progs { 247 if i >= len(tt.progs) { 248 break 249 } 250 ph := &tt.progs[i] 251 if !reflect.DeepEqual(&p.ProgHeader, ph) { 252 t.Errorf("open %s, program %d:\n\thave %#v\n\twant %#v\n", tt.file, i, &p.ProgHeader, ph) 253 } 254 } 255 tn := len(tt.sections) 256 fn := len(f.Sections) 257 if tn != fn { 258 t.Errorf("open %s: len(Sections) = %d, want %d", tt.file, fn, tn) 259 } 260 tn = len(tt.progs) 261 fn = len(f.Progs) 262 if tn != fn { 263 t.Errorf("open %s: len(Progs) = %d, want %d", tt.file, fn, tn) 264 } 265 tl := tt.needed 266 fl, err := f.ImportedLibraries() 267 if err != nil { 268 t.Error(err) 269 } 270 if !reflect.DeepEqual(tl, fl) { 271 t.Errorf("open %s: DT_NEEDED = %v, want %v", tt.file, tl, fl) 272 } 273 } 274 } 275 276 // elf.NewFile requires io.ReaderAt, which compress/gzip cannot 277 // provide. Decompress the file to a bytes.Reader. 278 func decompress(gz string) (io.ReaderAt, error) { 279 in, err := os.Open(gz) 280 if err != nil { 281 return nil, err 282 } 283 defer in.Close() 284 r, err := gzip.NewReader(in) 285 if err != nil { 286 return nil, err 287 } 288 var out bytes.Buffer 289 _, err = io.Copy(&out, r) 290 return bytes.NewReader(out.Bytes()), err 291 } 292 293 type relocationTestEntry struct { 294 entryNumber int 295 entry *dwarf.Entry 296 pcRanges [][2]uint64 297 } 298 299 type relocationTest struct { 300 file string 301 entries []relocationTestEntry 302 } 303 304 var relocationTests = []relocationTest{ 305 { 306 "testdata/go-relocation-test-gcc441-x86-64.obj", 307 []relocationTestEntry{ 308 { 309 entry: &dwarf.Entry{ 310 Offset: 0xb, 311 Tag: dwarf.TagCompileUnit, 312 Children: true, 313 Field: []dwarf.Field{ 314 {Attr: dwarf.AttrProducer, Val: "GNU C 4.4.1", Class: dwarf.ClassString}, 315 {Attr: dwarf.AttrLanguage, Val: int64(1), Class: dwarf.ClassConstant}, 316 {Attr: dwarf.AttrName, Val: "go-relocation-test.c", Class: dwarf.ClassString}, 317 {Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString}, 318 {Attr: dwarf.AttrLowpc, Val: uint64(0x0), Class: dwarf.ClassAddress}, 319 {Attr: dwarf.AttrHighpc, Val: uint64(0x6), Class: dwarf.ClassAddress}, 320 {Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr}, 321 }, 322 }, 323 pcRanges: [][2]uint64{{0x0, 0x6}}, 324 }, 325 }, 326 }, 327 { 328 "testdata/go-relocation-test-gcc441-x86.obj", 329 []relocationTestEntry{ 330 { 331 entry: &dwarf.Entry{ 332 Offset: 0xb, 333 Tag: dwarf.TagCompileUnit, 334 Children: true, 335 Field: []dwarf.Field{ 336 {Attr: dwarf.AttrProducer, Val: "GNU C 4.4.1", Class: dwarf.ClassString}, 337 {Attr: dwarf.AttrLanguage, Val: int64(1), Class: dwarf.ClassConstant}, 338 {Attr: dwarf.AttrName, Val: "t.c", Class: dwarf.ClassString}, 339 {Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString}, 340 {Attr: dwarf.AttrLowpc, Val: uint64(0x0), Class: dwarf.ClassAddress}, 341 {Attr: dwarf.AttrHighpc, Val: uint64(0x5), Class: dwarf.ClassAddress}, 342 {Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr}, 343 }, 344 }, 345 pcRanges: [][2]uint64{{0x0, 0x5}}, 346 }, 347 }, 348 }, 349 { 350 "testdata/go-relocation-test-gcc424-x86-64.obj", 351 []relocationTestEntry{ 352 { 353 entry: &dwarf.Entry{ 354 Offset: 0xb, 355 Tag: dwarf.TagCompileUnit, 356 Children: true, 357 Field: []dwarf.Field{ 358 {Attr: dwarf.AttrProducer, Val: "GNU C 4.2.4 (Ubuntu 4.2.4-1ubuntu4)", Class: dwarf.ClassString}, 359 {Attr: dwarf.AttrLanguage, Val: int64(1), Class: dwarf.ClassConstant}, 360 {Attr: dwarf.AttrName, Val: "go-relocation-test-gcc424.c", Class: dwarf.ClassString}, 361 {Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString}, 362 {Attr: dwarf.AttrLowpc, Val: uint64(0x0), Class: dwarf.ClassAddress}, 363 {Attr: dwarf.AttrHighpc, Val: uint64(0x6), Class: dwarf.ClassAddress}, 364 {Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr}, 365 }, 366 }, 367 pcRanges: [][2]uint64{{0x0, 0x6}}, 368 }, 369 }, 370 }, 371 { 372 "testdata/go-relocation-test-gcc482-aarch64.obj", 373 []relocationTestEntry{ 374 { 375 entry: &dwarf.Entry{ 376 Offset: 0xb, 377 Tag: dwarf.TagCompileUnit, 378 Children: true, 379 Field: []dwarf.Field{ 380 {Attr: dwarf.AttrProducer, Val: "GNU C 4.8.2 -g -fstack-protector", Class: dwarf.ClassString}, 381 {Attr: dwarf.AttrLanguage, Val: int64(1), Class: dwarf.ClassConstant}, 382 {Attr: dwarf.AttrName, Val: "go-relocation-test-gcc482.c", Class: dwarf.ClassString}, 383 {Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString}, 384 {Attr: dwarf.AttrLowpc, Val: uint64(0x0), Class: dwarf.ClassAddress}, 385 {Attr: dwarf.AttrHighpc, Val: int64(0x24), Class: dwarf.ClassConstant}, 386 {Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr}, 387 }, 388 }, 389 pcRanges: [][2]uint64{{0x0, 0x24}}, 390 }, 391 }, 392 }, 393 { 394 "testdata/go-relocation-test-gcc492-arm.obj", 395 []relocationTestEntry{ 396 { 397 entry: &dwarf.Entry{ 398 Offset: 0xb, 399 Tag: dwarf.TagCompileUnit, 400 Children: true, 401 Field: []dwarf.Field{ 402 {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}, 403 {Attr: dwarf.AttrLanguage, Val: int64(1), Class: dwarf.ClassConstant}, 404 {Attr: dwarf.AttrName, Val: "go-relocation-test-gcc492.c", Class: dwarf.ClassString}, 405 {Attr: dwarf.AttrCompDir, Val: "/root/go/src/debug/elf/testdata", Class: dwarf.ClassString}, 406 {Attr: dwarf.AttrLowpc, Val: uint64(0x0), Class: dwarf.ClassAddress}, 407 {Attr: dwarf.AttrHighpc, Val: int64(0x28), Class: dwarf.ClassConstant}, 408 {Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr}, 409 }, 410 }, 411 pcRanges: [][2]uint64{{0x0, 0x28}}, 412 }, 413 }, 414 }, 415 { 416 "testdata/go-relocation-test-clang-arm.obj", 417 []relocationTestEntry{ 418 { 419 entry: &dwarf.Entry{ 420 Offset: 0xb, 421 Tag: dwarf.TagCompileUnit, 422 Children: true, 423 Field: []dwarf.Field{ 424 {Attr: dwarf.AttrProducer, Val: "Debian clang version 3.5.0-10 (tags/RELEASE_350/final) (based on LLVM 3.5.0)", Class: dwarf.ClassString}, 425 {Attr: dwarf.AttrLanguage, Val: int64(12), Class: dwarf.ClassConstant}, 426 {Attr: dwarf.AttrName, Val: "hello.c", Class: dwarf.ClassString}, 427 {Attr: dwarf.AttrStmtList, Val: int64(0x0), Class: dwarf.ClassLinePtr}, 428 {Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString}, 429 {Attr: dwarf.AttrLowpc, Val: uint64(0x0), Class: dwarf.ClassAddress}, 430 {Attr: dwarf.AttrHighpc, Val: int64(0x30), Class: dwarf.ClassConstant}, 431 }, 432 }, 433 pcRanges: [][2]uint64{{0x0, 0x30}}, 434 }, 435 }, 436 }, 437 { 438 "testdata/go-relocation-test-gcc5-ppc.obj", 439 []relocationTestEntry{ 440 { 441 entry: &dwarf.Entry{ 442 Offset: 0xb, 443 Tag: dwarf.TagCompileUnit, 444 Children: true, 445 Field: []dwarf.Field{ 446 {Attr: dwarf.AttrProducer, Val: "GNU C11 5.0.0 20150116 (experimental) -Asystem=linux -Asystem=unix -Asystem=posix -g", Class: dwarf.ClassString}, 447 {Attr: dwarf.AttrLanguage, Val: int64(12), Class: dwarf.ClassConstant}, 448 {Attr: dwarf.AttrName, Val: "go-relocation-test-gcc5-ppc.c", Class: dwarf.ClassString}, 449 {Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString}, 450 {Attr: dwarf.AttrLowpc, Val: uint64(0x0), Class: dwarf.ClassAddress}, 451 {Attr: dwarf.AttrHighpc, Val: int64(0x44), Class: dwarf.ClassConstant}, 452 {Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr}, 453 }, 454 }, 455 pcRanges: [][2]uint64{{0x0, 0x44}}, 456 }, 457 }, 458 }, 459 { 460 "testdata/go-relocation-test-gcc482-ppc64le.obj", 461 []relocationTestEntry{ 462 { 463 entry: &dwarf.Entry{ 464 Offset: 0xb, 465 Tag: dwarf.TagCompileUnit, 466 Children: true, 467 Field: []dwarf.Field{ 468 {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}, 469 {Attr: dwarf.AttrLanguage, Val: int64(1), Class: dwarf.ClassConstant}, 470 {Attr: dwarf.AttrName, Val: "go-relocation-test-gcc482-ppc64le.c", Class: dwarf.ClassString}, 471 {Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString}, 472 {Attr: dwarf.AttrLowpc, Val: uint64(0x0), Class: dwarf.ClassAddress}, 473 {Attr: dwarf.AttrHighpc, Val: uint64(0x24), Class: dwarf.ClassAddress}, 474 {Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr}, 475 }, 476 }, 477 pcRanges: [][2]uint64{{0x0, 0x24}}, 478 }, 479 }, 480 }, 481 { 482 "testdata/go-relocation-test-gcc492-mips64.obj", 483 []relocationTestEntry{ 484 { 485 entry: &dwarf.Entry{ 486 Offset: 0xb, 487 Tag: dwarf.TagCompileUnit, 488 Children: true, 489 Field: []dwarf.Field{ 490 {Attr: dwarf.AttrProducer, Val: "GNU C 4.9.2 -meb -mabi=64 -march=mips3 -mtune=mips64 -mllsc -mno-shared -g", Class: dwarf.ClassString}, 491 {Attr: dwarf.AttrLanguage, Val: int64(1), Class: dwarf.ClassConstant}, 492 {Attr: dwarf.AttrName, Val: "hello.c", Class: dwarf.ClassString}, 493 {Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString}, 494 {Attr: dwarf.AttrLowpc, Val: uint64(0x0), Class: dwarf.ClassAddress}, 495 {Attr: dwarf.AttrHighpc, Val: int64(0x64), Class: dwarf.ClassConstant}, 496 {Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr}, 497 }, 498 }, 499 pcRanges: [][2]uint64{{0x0, 0x64}}, 500 }, 501 }, 502 }, 503 { 504 "testdata/go-relocation-test-gcc531-s390x.obj", 505 []relocationTestEntry{ 506 { 507 entry: &dwarf.Entry{ 508 Offset: 0xb, 509 Tag: dwarf.TagCompileUnit, 510 Children: true, 511 Field: []dwarf.Field{ 512 {Attr: dwarf.AttrProducer, Val: "GNU C11 5.3.1 20160316 -march=zEC12 -m64 -mzarch -g -fstack-protector-strong", Class: dwarf.ClassString}, 513 {Attr: dwarf.AttrLanguage, Val: int64(12), Class: dwarf.ClassConstant}, 514 {Attr: dwarf.AttrName, Val: "hello.c", Class: dwarf.ClassString}, 515 {Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString}, 516 {Attr: dwarf.AttrLowpc, Val: uint64(0x0), Class: dwarf.ClassAddress}, 517 {Attr: dwarf.AttrHighpc, Val: int64(0x3a), Class: dwarf.ClassConstant}, 518 {Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr}, 519 }, 520 }, 521 pcRanges: [][2]uint64{{0x0, 0x3a}}, 522 }, 523 }, 524 }, 525 { 526 "testdata/go-relocation-test-gcc620-sparc64.obj", 527 []relocationTestEntry{ 528 { 529 entry: &dwarf.Entry{ 530 Offset: 0xb, 531 Tag: dwarf.TagCompileUnit, 532 Children: true, 533 Field: []dwarf.Field{ 534 {Attr: dwarf.AttrProducer, Val: "GNU C11 6.2.0 20160914 -mcpu=v9 -g -fstack-protector-strong", Class: dwarf.ClassString}, 535 {Attr: dwarf.AttrLanguage, Val: int64(12), Class: dwarf.ClassConstant}, 536 {Attr: dwarf.AttrName, Val: "hello.c", Class: dwarf.ClassString}, 537 {Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString}, 538 {Attr: dwarf.AttrLowpc, Val: uint64(0x0), Class: dwarf.ClassAddress}, 539 {Attr: dwarf.AttrHighpc, Val: int64(0x2c), Class: dwarf.ClassConstant}, 540 {Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr}, 541 }, 542 }, 543 pcRanges: [][2]uint64{{0x0, 0x2c}}, 544 }, 545 }, 546 }, 547 { 548 "testdata/go-relocation-test-gcc492-mipsle.obj", 549 []relocationTestEntry{ 550 { 551 entry: &dwarf.Entry{ 552 Offset: 0xb, 553 Tag: dwarf.TagCompileUnit, 554 Children: true, 555 Field: []dwarf.Field{ 556 {Attr: dwarf.AttrProducer, Val: "GNU C 4.9.2 -mel -march=mips2 -mtune=mips32 -mllsc -mno-shared -mabi=32 -g", Class: dwarf.ClassString}, 557 {Attr: dwarf.AttrLanguage, Val: int64(1), Class: dwarf.ClassConstant}, 558 {Attr: dwarf.AttrName, Val: "hello.c", Class: dwarf.ClassString}, 559 {Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString}, 560 {Attr: dwarf.AttrLowpc, Val: uint64(0x0), Class: dwarf.ClassAddress}, 561 {Attr: dwarf.AttrHighpc, Val: int64(0x58), Class: dwarf.ClassConstant}, 562 {Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr}, 563 }, 564 }, 565 pcRanges: [][2]uint64{{0x0, 0x58}}, 566 }, 567 }, 568 }, 569 { 570 "testdata/go-relocation-test-gcc540-mips.obj", 571 []relocationTestEntry{ 572 { 573 entry: &dwarf.Entry{ 574 Offset: 0xb, 575 Tag: dwarf.TagCompileUnit, 576 Children: true, 577 Field: []dwarf.Field{ 578 {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}, 579 {Attr: dwarf.AttrLanguage, Val: int64(12), Class: dwarf.ClassConstant}, 580 {Attr: dwarf.AttrName, Val: "hello.c", Class: dwarf.ClassString}, 581 {Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString}, 582 {Attr: dwarf.AttrLowpc, Val: uint64(0x0), Class: dwarf.ClassAddress}, 583 {Attr: dwarf.AttrHighpc, Val: uint64(0x5c), Class: dwarf.ClassAddress}, 584 {Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr}, 585 }, 586 }, 587 pcRanges: [][2]uint64{{0x0, 0x5c}}, 588 }, 589 }, 590 }, 591 { 592 "testdata/go-relocation-test-gcc493-mips64le.obj", 593 []relocationTestEntry{ 594 { 595 entry: &dwarf.Entry{ 596 Offset: 0xb, 597 Tag: dwarf.TagCompileUnit, 598 Children: true, 599 Field: []dwarf.Field{ 600 {Attr: dwarf.AttrProducer, Val: "GNU C 4.9.3 -mel -mabi=64 -mllsc -mno-shared -g -fstack-protector-strong", Class: dwarf.ClassString}, 601 {Attr: dwarf.AttrLanguage, Val: int64(1), Class: dwarf.ClassConstant}, 602 {Attr: dwarf.AttrName, Val: "hello.c", Class: dwarf.ClassString}, 603 {Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString}, 604 {Attr: dwarf.AttrLowpc, Val: uint64(0x0), Class: dwarf.ClassAddress}, 605 {Attr: dwarf.AttrHighpc, Val: int64(0x64), Class: dwarf.ClassConstant}, 606 {Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr}, 607 }, 608 }, 609 pcRanges: [][2]uint64{{0x0, 0x64}}, 610 }, 611 }, 612 }, 613 { 614 "testdata/go-relocation-test-gcc720-riscv64.obj", 615 []relocationTestEntry{ 616 { 617 entry: &dwarf.Entry{ 618 Offset: 0xb, 619 Tag: dwarf.TagCompileUnit, 620 Children: true, 621 Field: []dwarf.Field{ 622 {Attr: dwarf.AttrProducer, Val: "GNU C11 7.2.0 -march=rv64imafdc -mabi=lp64d -g -gdwarf-2", Class: dwarf.ClassString}, 623 {Attr: dwarf.AttrLanguage, Val: int64(12), Class: dwarf.ClassConstant}, 624 {Attr: dwarf.AttrName, Val: "hello.c", Class: dwarf.ClassString}, 625 {Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString}, 626 {Attr: dwarf.AttrLowpc, Val: uint64(0x0), Class: dwarf.ClassAddress}, 627 {Attr: dwarf.AttrHighpc, Val: uint64(0x2c), Class: dwarf.ClassAddress}, 628 {Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr}, 629 }, 630 }, 631 pcRanges: [][2]uint64{{0x0, 0x2c}}, 632 }, 633 }, 634 }, 635 { 636 "testdata/go-relocation-test-clang-x86.obj", 637 []relocationTestEntry{ 638 { 639 entry: &dwarf.Entry{ 640 Offset: 0xb, 641 Tag: dwarf.TagCompileUnit, 642 Children: true, 643 Field: []dwarf.Field{ 644 {Attr: dwarf.AttrProducer, Val: "clang version google3-trunk (trunk r209387)", Class: dwarf.ClassString}, 645 {Attr: dwarf.AttrLanguage, Val: int64(12), Class: dwarf.ClassConstant}, 646 {Attr: dwarf.AttrName, Val: "go-relocation-test-clang.c", Class: dwarf.ClassString}, 647 {Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr}, 648 {Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString}, 649 }, 650 }, 651 }, 652 }, 653 }, 654 { 655 "testdata/gcc-amd64-openbsd-debug-with-rela.obj", 656 []relocationTestEntry{ 657 { 658 entryNumber: 203, 659 entry: &dwarf.Entry{ 660 Offset: 0xc62, 661 Tag: dwarf.TagMember, 662 Children: false, 663 Field: []dwarf.Field{ 664 {Attr: dwarf.AttrName, Val: "it_interval", Class: dwarf.ClassString}, 665 {Attr: dwarf.AttrDeclFile, Val: int64(7), Class: dwarf.ClassConstant}, 666 {Attr: dwarf.AttrDeclLine, Val: int64(236), Class: dwarf.ClassConstant}, 667 {Attr: dwarf.AttrType, Val: dwarf.Offset(0xb7f), Class: dwarf.ClassReference}, 668 {Attr: dwarf.AttrDataMemberLoc, Val: []byte{0x23, 0x0}, Class: dwarf.ClassExprLoc}, 669 }, 670 }, 671 }, 672 { 673 entryNumber: 204, 674 entry: &dwarf.Entry{ 675 Offset: 0xc70, 676 Tag: dwarf.TagMember, 677 Children: false, 678 Field: []dwarf.Field{ 679 {Attr: dwarf.AttrName, Val: "it_value", Class: dwarf.ClassString}, 680 {Attr: dwarf.AttrDeclFile, Val: int64(7), Class: dwarf.ClassConstant}, 681 {Attr: dwarf.AttrDeclLine, Val: int64(237), Class: dwarf.ClassConstant}, 682 {Attr: dwarf.AttrType, Val: dwarf.Offset(0xb7f), Class: dwarf.ClassReference}, 683 {Attr: dwarf.AttrDataMemberLoc, Val: []byte{0x23, 0x10}, Class: dwarf.ClassExprLoc}, 684 }, 685 }, 686 }, 687 }, 688 }, 689 { 690 "testdata/go-relocation-test-gcc930-ranges-no-rela-x86-64", 691 []relocationTestEntry{ 692 { 693 entry: &dwarf.Entry{ 694 Offset: 0xb, 695 Tag: dwarf.TagCompileUnit, 696 Children: true, 697 Field: []dwarf.Field{ 698 {Attr: dwarf.AttrProducer, Val: "GNU C17 9.3.0 -mtune=generic -march=x86-64 -g -fno-asynchronous-unwind-tables", Class: dwarf.ClassString}, 699 {Attr: dwarf.AttrLanguage, Val: int64(12), Class: dwarf.ClassConstant}, 700 {Attr: dwarf.AttrName, Val: "multiple-code-sections.c", Class: dwarf.ClassString}, 701 {Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString}, 702 {Attr: dwarf.AttrRanges, Val: int64(0), Class: dwarf.ClassRangeListPtr}, 703 {Attr: dwarf.AttrLowpc, Val: uint64(0), Class: dwarf.ClassAddress}, 704 {Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr}, 705 }, 706 }, 707 pcRanges: [][2]uint64{ 708 {0x765, 0x777}, 709 {0x7e1, 0x7ec}, 710 }, 711 }, 712 }, 713 }, 714 { 715 "testdata/go-relocation-test-gcc930-ranges-with-rela-x86-64", 716 []relocationTestEntry{ 717 { 718 entry: &dwarf.Entry{ 719 Offset: 0xb, 720 Tag: dwarf.TagCompileUnit, 721 Children: true, 722 Field: []dwarf.Field{ 723 {Attr: dwarf.AttrProducer, Val: "GNU C17 9.3.0 -mtune=generic -march=x86-64 -g -fno-asynchronous-unwind-tables", Class: dwarf.ClassString}, 724 {Attr: dwarf.AttrLanguage, Val: int64(12), Class: dwarf.ClassConstant}, 725 {Attr: dwarf.AttrName, Val: "multiple-code-sections.c", Class: dwarf.ClassString}, 726 {Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString}, 727 {Attr: dwarf.AttrRanges, Val: int64(0), Class: dwarf.ClassRangeListPtr}, 728 {Attr: dwarf.AttrLowpc, Val: uint64(0), Class: dwarf.ClassAddress}, 729 {Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr}, 730 }, 731 }, 732 pcRanges: [][2]uint64{ 733 {0x765, 0x777}, 734 {0x7e1, 0x7ec}, 735 }, 736 }, 737 }, 738 }, 739 } 740 741 func TestDWARFRelocations(t *testing.T) { 742 for _, test := range relocationTests { 743 test := test 744 t.Run(test.file, func(t *testing.T) { 745 t.Parallel() 746 f, err := Open(test.file) 747 if err != nil { 748 t.Fatal(err) 749 } 750 dwarf, err := f.DWARF() 751 if err != nil { 752 t.Fatal(err) 753 } 754 reader := dwarf.Reader() 755 idx := 0 756 for _, testEntry := range test.entries { 757 if testEntry.entryNumber < idx { 758 t.Fatalf("internal test error: %d < %d", testEntry.entryNumber, idx) 759 } 760 for ; idx < testEntry.entryNumber; idx++ { 761 entry, err := reader.Next() 762 if entry == nil || err != nil { 763 t.Fatalf("Failed to skip to entry %d: %v", testEntry.entryNumber, err) 764 } 765 } 766 entry, err := reader.Next() 767 idx++ 768 if err != nil { 769 t.Fatal(err) 770 } 771 if !reflect.DeepEqual(testEntry.entry, entry) { 772 t.Errorf("entry %d mismatch: got:%#v want:%#v", testEntry.entryNumber, entry, testEntry.entry) 773 } 774 pcRanges, err := dwarf.Ranges(entry) 775 if err != nil { 776 t.Fatal(err) 777 } 778 if !reflect.DeepEqual(testEntry.pcRanges, pcRanges) { 779 t.Errorf("entry %d: PC range mismatch: got:%#v want:%#v", testEntry.entryNumber, pcRanges, testEntry.pcRanges) 780 } 781 } 782 }) 783 } 784 } 785 786 func TestCompressedDWARF(t *testing.T) { 787 // Test file built with GCC 4.8.4 and as 2.24 using: 788 // gcc -Wa,--compress-debug-sections -g -c -o zdebug-test-gcc484-x86-64.obj hello.c 789 f, err := Open("testdata/zdebug-test-gcc484-x86-64.obj") 790 if err != nil { 791 t.Fatal(err) 792 } 793 dwarf, err := f.DWARF() 794 if err != nil { 795 t.Fatal(err) 796 } 797 reader := dwarf.Reader() 798 n := 0 799 for { 800 entry, err := reader.Next() 801 if err != nil { 802 t.Fatal(err) 803 } 804 if entry == nil { 805 break 806 } 807 n++ 808 } 809 if n != 18 { 810 t.Fatalf("want %d DWARF entries, got %d", 18, n) 811 } 812 } 813 814 func TestCompressedSection(t *testing.T) { 815 // Test files built with gcc -g -S hello.c and assembled with 816 // --compress-debug-sections=zlib-gabi. 817 f, err := Open("testdata/compressed-64.obj") 818 if err != nil { 819 t.Fatal(err) 820 } 821 sec := f.Section(".debug_info") 822 wantData := []byte{ 823 182, 0, 0, 0, 4, 0, 0, 0, 0, 0, 8, 1, 0, 0, 0, 0, 824 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 825 0, 27, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 8, 7, 826 0, 0, 0, 0, 2, 1, 8, 0, 0, 0, 0, 2, 2, 7, 0, 0, 827 0, 0, 2, 4, 7, 0, 0, 0, 0, 2, 1, 6, 0, 0, 0, 0, 828 2, 2, 5, 0, 0, 0, 0, 3, 4, 5, 105, 110, 116, 0, 2, 8, 829 5, 0, 0, 0, 0, 2, 8, 7, 0, 0, 0, 0, 4, 8, 114, 0, 830 0, 0, 2, 1, 6, 0, 0, 0, 0, 5, 0, 0, 0, 0, 1, 4, 831 0, 0, 0, 0, 0, 0, 0, 0, 27, 0, 0, 0, 0, 0, 0, 0, 832 1, 156, 179, 0, 0, 0, 6, 0, 0, 0, 0, 1, 4, 87, 0, 0, 833 0, 2, 145, 108, 6, 0, 0, 0, 0, 1, 4, 179, 0, 0, 0, 2, 834 145, 96, 0, 4, 8, 108, 0, 0, 0, 0, 835 } 836 837 // Test Data method. 838 b, err := sec.Data() 839 if err != nil { 840 t.Fatal(err) 841 } 842 if !bytes.Equal(wantData, b) { 843 t.Fatalf("want data %x, got %x", wantData, b) 844 } 845 846 // Test Open method and seeking. 847 buf, have, count := make([]byte, len(b)), make([]bool, len(b)), 0 848 sf := sec.Open() 849 if got, err := sf.Seek(0, io.SeekEnd); got != int64(len(b)) || err != nil { 850 t.Fatalf("want seek end %d, got %d error %v", len(b), got, err) 851 } 852 if n, err := sf.Read(buf); n != 0 || err != io.EOF { 853 t.Fatalf("want EOF with 0 bytes, got %v with %d bytes", err, n) 854 } 855 pos := int64(len(buf)) 856 for count < len(buf) { 857 // Construct random seek arguments. 858 whence := rand.Intn(3) 859 target := rand.Int63n(int64(len(buf))) 860 var offset int64 861 switch whence { 862 case io.SeekStart: 863 offset = target 864 case io.SeekCurrent: 865 offset = target - pos 866 case io.SeekEnd: 867 offset = target - int64(len(buf)) 868 } 869 pos, err = sf.Seek(offset, whence) 870 if err != nil { 871 t.Fatal(err) 872 } 873 if pos != target { 874 t.Fatalf("want position %d, got %d", target, pos) 875 } 876 877 // Read data from the new position. 878 end := pos + 16 879 if end > int64(len(buf)) { 880 end = int64(len(buf)) 881 } 882 n, err := io.ReadFull(sf, buf[pos:end]) 883 if err != nil { 884 t.Fatal(err) 885 } 886 for i := 0; i < n; i++ { 887 if !have[pos] { 888 have[pos] = true 889 count++ 890 } 891 pos++ 892 } 893 } 894 if !bytes.Equal(wantData, buf) { 895 t.Fatalf("want data %x, got %x", wantData, buf) 896 } 897 } 898 899 func TestNoSectionOverlaps(t *testing.T) { 900 // Ensure cmd/link outputs sections without overlaps. 901 switch runtime.GOOS { 902 case "aix", "android", "darwin", "ios", "js", "plan9", "windows": 903 t.Skipf("cmd/link doesn't produce ELF binaries on %s", runtime.GOOS) 904 } 905 _ = net.ResolveIPAddr // force dynamic linkage 906 f, err := Open(os.Args[0]) 907 if err != nil { 908 t.Error(err) 909 return 910 } 911 for i, si := range f.Sections { 912 sih := si.SectionHeader 913 if sih.Type == SHT_NOBITS { 914 continue 915 } 916 for j, sj := range f.Sections { 917 sjh := sj.SectionHeader 918 if i == j || sjh.Type == SHT_NOBITS || sih.Offset == sjh.Offset && sih.Size == 0 { 919 continue 920 } 921 if sih.Offset >= sjh.Offset && sih.Offset < sjh.Offset+sjh.Size { 922 t.Errorf("ld produced ELF with section %s within %s: 0x%x <= 0x%x..0x%x < 0x%x", 923 sih.Name, sjh.Name, sjh.Offset, sih.Offset, sih.Offset+sih.Size, sjh.Offset+sjh.Size) 924 } 925 } 926 } 927 } 928 929 func TestIssue10996(t *testing.T) { 930 data := []byte("\u007fELF\x02\x01\x010000000000000" + 931 "\x010000000000000000000" + 932 "\x00\x00\x00\x00\x00\x00\x00\x0000000000\x00\x00\x00\x00" + 933 "0000") 934 _, err := NewFile(bytes.NewReader(data)) 935 if err == nil { 936 t.Fatalf("opening invalid ELF file unexpectedly succeeded") 937 } 938 }