github.com/riscv/riscv-go@v0.0.0-20200123204226-124ebd6fcc8e/src/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 } 297 298 type relocationTest struct { 299 file string 300 entries []relocationTestEntry 301 } 302 303 var relocationTests = []relocationTest{ 304 { 305 "testdata/go-relocation-test-gcc441-x86-64.obj", 306 []relocationTestEntry{ 307 {0, &dwarf.Entry{ 308 Offset: 0xb, 309 Tag: dwarf.TagCompileUnit, 310 Children: true, 311 Field: []dwarf.Field{ 312 {Attr: dwarf.AttrProducer, Val: "GNU C 4.4.1", Class: dwarf.ClassString}, 313 {Attr: dwarf.AttrLanguage, Val: int64(1), Class: dwarf.ClassConstant}, 314 {Attr: dwarf.AttrName, Val: "go-relocation-test.c", Class: dwarf.ClassString}, 315 {Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString}, 316 {Attr: dwarf.AttrLowpc, Val: uint64(0x0), Class: dwarf.ClassAddress}, 317 {Attr: dwarf.AttrHighpc, Val: uint64(0x6), Class: dwarf.ClassAddress}, 318 {Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr}, 319 }, 320 }}, 321 }, 322 }, 323 { 324 "testdata/go-relocation-test-gcc441-x86.obj", 325 []relocationTestEntry{ 326 {0, &dwarf.Entry{ 327 Offset: 0xb, 328 Tag: dwarf.TagCompileUnit, 329 Children: true, 330 Field: []dwarf.Field{ 331 {Attr: dwarf.AttrProducer, Val: "GNU C 4.4.1", Class: dwarf.ClassString}, 332 {Attr: dwarf.AttrLanguage, Val: int64(1), Class: dwarf.ClassConstant}, 333 {Attr: dwarf.AttrName, Val: "t.c", Class: dwarf.ClassString}, 334 {Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString}, 335 {Attr: dwarf.AttrLowpc, Val: uint64(0x0), Class: dwarf.ClassAddress}, 336 {Attr: dwarf.AttrHighpc, Val: uint64(0x5), Class: dwarf.ClassAddress}, 337 {Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr}, 338 }, 339 }}, 340 }, 341 }, 342 { 343 "testdata/go-relocation-test-gcc424-x86-64.obj", 344 []relocationTestEntry{ 345 {0, &dwarf.Entry{ 346 Offset: 0xb, 347 Tag: dwarf.TagCompileUnit, 348 Children: true, 349 Field: []dwarf.Field{ 350 {Attr: dwarf.AttrProducer, Val: "GNU C 4.2.4 (Ubuntu 4.2.4-1ubuntu4)", Class: dwarf.ClassString}, 351 {Attr: dwarf.AttrLanguage, Val: int64(1), Class: dwarf.ClassConstant}, 352 {Attr: dwarf.AttrName, Val: "go-relocation-test-gcc424.c", Class: dwarf.ClassString}, 353 {Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString}, 354 {Attr: dwarf.AttrLowpc, Val: uint64(0x0), Class: dwarf.ClassAddress}, 355 {Attr: dwarf.AttrHighpc, Val: uint64(0x6), Class: dwarf.ClassAddress}, 356 {Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr}, 357 }, 358 }}, 359 }, 360 }, 361 { 362 "testdata/go-relocation-test-gcc482-aarch64.obj", 363 []relocationTestEntry{ 364 {0, &dwarf.Entry{ 365 Offset: 0xb, 366 Tag: dwarf.TagCompileUnit, 367 Children: true, 368 Field: []dwarf.Field{ 369 {Attr: dwarf.AttrProducer, Val: "GNU C 4.8.2 -g -fstack-protector", Class: dwarf.ClassString}, 370 {Attr: dwarf.AttrLanguage, Val: int64(1), Class: dwarf.ClassConstant}, 371 {Attr: dwarf.AttrName, Val: "go-relocation-test-gcc482.c", Class: dwarf.ClassString}, 372 {Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString}, 373 {Attr: dwarf.AttrLowpc, Val: uint64(0x0), Class: dwarf.ClassAddress}, 374 {Attr: dwarf.AttrHighpc, Val: int64(0x24), Class: dwarf.ClassConstant}, 375 {Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr}, 376 }, 377 }}, 378 }, 379 }, 380 { 381 "testdata/go-relocation-test-gcc492-arm.obj", 382 []relocationTestEntry{ 383 {0, &dwarf.Entry{ 384 Offset: 0xb, 385 Tag: dwarf.TagCompileUnit, 386 Children: true, 387 Field: []dwarf.Field{ 388 {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}, 389 {Attr: dwarf.AttrLanguage, Val: int64(1), Class: dwarf.ClassConstant}, 390 {Attr: dwarf.AttrName, Val: "go-relocation-test-gcc492.c", Class: dwarf.ClassString}, 391 {Attr: dwarf.AttrCompDir, Val: "/root/go/src/debug/elf/testdata", Class: dwarf.ClassString}, 392 {Attr: dwarf.AttrLowpc, Val: uint64(0x0), Class: dwarf.ClassAddress}, 393 {Attr: dwarf.AttrHighpc, Val: int64(0x28), Class: dwarf.ClassConstant}, 394 {Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr}, 395 }, 396 }}, 397 }, 398 }, 399 { 400 "testdata/go-relocation-test-clang-arm.obj", 401 []relocationTestEntry{ 402 {0, &dwarf.Entry{ 403 Offset: 0xb, 404 Tag: dwarf.TagCompileUnit, 405 Children: true, 406 Field: []dwarf.Field{ 407 {Attr: dwarf.AttrProducer, Val: "Debian clang version 3.5.0-10 (tags/RELEASE_350/final) (based on LLVM 3.5.0)", Class: dwarf.ClassString}, 408 {Attr: dwarf.AttrLanguage, Val: int64(12), Class: dwarf.ClassConstant}, 409 {Attr: dwarf.AttrName, Val: "hello.c", Class: dwarf.ClassString}, 410 {Attr: dwarf.AttrStmtList, Val: int64(0x0), Class: dwarf.ClassLinePtr}, 411 {Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString}, 412 {Attr: dwarf.AttrLowpc, Val: uint64(0x0), Class: dwarf.ClassAddress}, 413 {Attr: dwarf.AttrHighpc, Val: int64(48), Class: dwarf.ClassConstant}, 414 }, 415 }}, 416 }, 417 }, 418 { 419 "testdata/go-relocation-test-gcc5-ppc.obj", 420 []relocationTestEntry{ 421 {0, &dwarf.Entry{ 422 Offset: 0xb, 423 Tag: dwarf.TagCompileUnit, 424 Children: true, 425 Field: []dwarf.Field{ 426 {Attr: dwarf.AttrProducer, Val: "GNU C11 5.0.0 20150116 (experimental) -Asystem=linux -Asystem=unix -Asystem=posix -g", Class: dwarf.ClassString}, 427 {Attr: dwarf.AttrLanguage, Val: int64(12), Class: dwarf.ClassConstant}, 428 {Attr: dwarf.AttrName, Val: "go-relocation-test-gcc5-ppc.c", Class: dwarf.ClassString}, 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(0x44), Class: dwarf.ClassConstant}, 432 {Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr}, 433 }, 434 }}, 435 }, 436 }, 437 { 438 "testdata/go-relocation-test-gcc482-ppc64le.obj", 439 []relocationTestEntry{ 440 {0, &dwarf.Entry{ 441 Offset: 0xb, 442 Tag: dwarf.TagCompileUnit, 443 Children: true, 444 Field: []dwarf.Field{ 445 {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}, 446 {Attr: dwarf.AttrLanguage, Val: int64(1), Class: dwarf.ClassConstant}, 447 {Attr: dwarf.AttrName, Val: "go-relocation-test-gcc482-ppc64le.c", Class: dwarf.ClassString}, 448 {Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString}, 449 {Attr: dwarf.AttrLowpc, Val: uint64(0x0), Class: dwarf.ClassAddress}, 450 {Attr: dwarf.AttrHighpc, Val: uint64(0x24), Class: dwarf.ClassAddress}, 451 {Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr}, 452 }, 453 }}, 454 }, 455 }, 456 { 457 "testdata/go-relocation-test-gcc492-mips64.obj", 458 []relocationTestEntry{ 459 {0, &dwarf.Entry{ 460 Offset: 0xb, 461 Tag: dwarf.TagCompileUnit, 462 Children: true, 463 Field: []dwarf.Field{ 464 {Attr: dwarf.AttrProducer, Val: "GNU C 4.9.2 -meb -mabi=64 -march=mips3 -mtune=mips64 -mllsc -mno-shared -g", Class: dwarf.ClassString}, 465 {Attr: dwarf.AttrLanguage, Val: int64(1), Class: dwarf.ClassConstant}, 466 {Attr: dwarf.AttrName, Val: "hello.c", Class: dwarf.ClassString}, 467 {Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString}, 468 {Attr: dwarf.AttrLowpc, Val: uint64(0x0), Class: dwarf.ClassAddress}, 469 {Attr: dwarf.AttrHighpc, Val: int64(100), Class: dwarf.ClassConstant}, 470 {Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr}, 471 }, 472 }}, 473 }, 474 }, 475 { 476 "testdata/go-relocation-test-gcc531-s390x.obj", 477 []relocationTestEntry{ 478 {0, &dwarf.Entry{ 479 Offset: 0xb, 480 Tag: dwarf.TagCompileUnit, 481 Children: true, 482 Field: []dwarf.Field{ 483 {Attr: dwarf.AttrProducer, Val: "GNU C11 5.3.1 20160316 -march=zEC12 -m64 -mzarch -g -fstack-protector-strong", Class: dwarf.ClassString}, 484 {Attr: dwarf.AttrLanguage, Val: int64(12), Class: dwarf.ClassConstant}, 485 {Attr: dwarf.AttrName, Val: "hello.c", Class: dwarf.ClassString}, 486 {Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString}, 487 {Attr: dwarf.AttrLowpc, Val: uint64(0x0), Class: dwarf.ClassAddress}, 488 {Attr: dwarf.AttrHighpc, Val: int64(58), Class: dwarf.ClassConstant}, 489 {Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr}, 490 }, 491 }}, 492 }, 493 }, 494 { 495 "testdata/go-relocation-test-gcc620-sparc64.obj", 496 []relocationTestEntry{ 497 {0, &dwarf.Entry{ 498 Offset: 0xb, 499 Tag: dwarf.TagCompileUnit, 500 Children: true, 501 Field: []dwarf.Field{ 502 {Attr: dwarf.AttrProducer, Val: "GNU C11 6.2.0 20160914 -mcpu=v9 -g -fstack-protector-strong", Class: dwarf.ClassString}, 503 {Attr: dwarf.AttrLanguage, Val: int64(12), Class: dwarf.ClassConstant}, 504 {Attr: dwarf.AttrName, Val: "hello.c", Class: dwarf.ClassString}, 505 {Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString}, 506 {Attr: dwarf.AttrLowpc, Val: uint64(0x0), Class: dwarf.ClassAddress}, 507 {Attr: dwarf.AttrHighpc, Val: int64(0x2c), Class: dwarf.ClassConstant}, 508 {Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr}, 509 }, 510 }}, 511 }, 512 }, 513 { 514 "testdata/go-relocation-test-gcc492-mipsle.obj", 515 []relocationTestEntry{ 516 {0, &dwarf.Entry{ 517 Offset: 0xb, 518 Tag: dwarf.TagCompileUnit, 519 Children: true, 520 Field: []dwarf.Field{ 521 {Attr: dwarf.AttrProducer, Val: "GNU C 4.9.2 -mel -march=mips2 -mtune=mips32 -mllsc -mno-shared -mabi=32 -g", Class: dwarf.ClassString}, 522 {Attr: dwarf.AttrLanguage, Val: int64(1), Class: dwarf.ClassConstant}, 523 {Attr: dwarf.AttrName, Val: "hello.c", Class: dwarf.ClassString}, 524 {Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString}, 525 {Attr: dwarf.AttrLowpc, Val: uint64(0x0), Class: dwarf.ClassAddress}, 526 {Attr: dwarf.AttrHighpc, Val: int64(0x58), Class: dwarf.ClassConstant}, 527 {Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr}, 528 }, 529 }}, 530 }, 531 }, 532 { 533 "testdata/go-relocation-test-gcc540-mips.obj", 534 []relocationTestEntry{ 535 {0, &dwarf.Entry{ 536 Offset: 0xb, 537 Tag: dwarf.TagCompileUnit, 538 Children: true, 539 Field: []dwarf.Field{ 540 {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}, 541 {Attr: dwarf.AttrLanguage, Val: int64(12), Class: dwarf.ClassConstant}, 542 {Attr: dwarf.AttrName, Val: "hello.c", Class: dwarf.ClassString}, 543 {Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString}, 544 {Attr: dwarf.AttrLowpc, Val: uint64(0x0), Class: dwarf.ClassAddress}, 545 {Attr: dwarf.AttrHighpc, Val: uint64(0x5c), Class: dwarf.ClassAddress}, 546 {Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr}, 547 }, 548 }}, 549 }, 550 }, 551 { 552 "testdata/go-relocation-test-gcc493-mips64le.obj", 553 []relocationTestEntry{ 554 {0, &dwarf.Entry{ 555 Offset: 0xb, 556 Tag: dwarf.TagCompileUnit, 557 Children: true, 558 Field: []dwarf.Field{ 559 {Attr: dwarf.AttrProducer, Val: "GNU C 4.9.3 -mel -mabi=64 -mllsc -mno-shared -g -fstack-protector-strong", Class: dwarf.ClassString}, 560 {Attr: dwarf.AttrLanguage, Val: int64(1), Class: dwarf.ClassConstant}, 561 {Attr: dwarf.AttrName, Val: "hello.c", Class: dwarf.ClassString}, 562 {Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString}, 563 {Attr: dwarf.AttrLowpc, Val: uint64(0x0), Class: dwarf.ClassAddress}, 564 {Attr: dwarf.AttrHighpc, Val: int64(100), Class: dwarf.ClassConstant}, 565 {Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr}, 566 }, 567 }}, 568 }, 569 }, 570 { 571 "testdata/go-relocation-test-clang-x86.obj", 572 []relocationTestEntry{ 573 {0, &dwarf.Entry{ 574 Offset: 0xb, 575 Tag: dwarf.TagCompileUnit, 576 Children: true, 577 Field: []dwarf.Field{ 578 {Attr: dwarf.AttrProducer, Val: "clang version google3-trunk (trunk r209387)", Class: dwarf.ClassString}, 579 {Attr: dwarf.AttrLanguage, Val: int64(12), Class: dwarf.ClassConstant}, 580 {Attr: dwarf.AttrName, Val: "go-relocation-test-clang.c", Class: dwarf.ClassString}, 581 {Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr}, 582 {Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString}, 583 }, 584 }}, 585 }, 586 }, 587 { 588 "testdata/gcc-amd64-openbsd-debug-with-rela.obj", 589 []relocationTestEntry{ 590 {203, &dwarf.Entry{ 591 Offset: 0xc62, 592 Tag: dwarf.TagMember, 593 Children: false, 594 Field: []dwarf.Field{ 595 {Attr: dwarf.AttrName, Val: "it_interval", Class: dwarf.ClassString}, 596 {Attr: dwarf.AttrDeclFile, Val: int64(7), Class: dwarf.ClassConstant}, 597 {Attr: dwarf.AttrDeclLine, Val: int64(236), Class: dwarf.ClassConstant}, 598 {Attr: dwarf.AttrType, Val: dwarf.Offset(0xb7f), Class: dwarf.ClassReference}, 599 {Attr: dwarf.AttrDataMemberLoc, Val: []byte{0x23, 0x0}, Class: dwarf.ClassExprLoc}, 600 }, 601 }}, 602 {204, &dwarf.Entry{ 603 Offset: 0xc70, 604 Tag: dwarf.TagMember, 605 Children: false, 606 Field: []dwarf.Field{ 607 {Attr: dwarf.AttrName, Val: "it_value", Class: dwarf.ClassString}, 608 {Attr: dwarf.AttrDeclFile, Val: int64(7), Class: dwarf.ClassConstant}, 609 {Attr: dwarf.AttrDeclLine, Val: int64(237), Class: dwarf.ClassConstant}, 610 {Attr: dwarf.AttrType, Val: dwarf.Offset(0xb7f), Class: dwarf.ClassReference}, 611 {Attr: dwarf.AttrDataMemberLoc, Val: []byte{0x23, 0x10}, Class: dwarf.ClassExprLoc}, 612 }, 613 }}, 614 }, 615 }, 616 } 617 618 func TestDWARFRelocations(t *testing.T) { 619 for i, test := range relocationTests { 620 f, err := Open(test.file) 621 if err != nil { 622 t.Error(err) 623 continue 624 } 625 dwarf, err := f.DWARF() 626 if err != nil { 627 t.Error(err) 628 continue 629 } 630 for _, testEntry := range test.entries { 631 reader := dwarf.Reader() 632 for j := 0; j < testEntry.entryNumber; j++ { 633 entry, err := reader.Next() 634 if entry == nil || err != nil { 635 t.Errorf("Failed to skip to entry %d: %v", testEntry.entryNumber, err) 636 continue 637 } 638 } 639 entry, err := reader.Next() 640 if err != nil { 641 t.Error(err) 642 continue 643 } 644 if !reflect.DeepEqual(testEntry.entry, entry) { 645 t.Errorf("#%d/%d: mismatch: got:%#v want:%#v", i, testEntry.entryNumber, entry, testEntry.entry) 646 continue 647 } 648 } 649 } 650 } 651 652 func TestCompressedDWARF(t *testing.T) { 653 // Test file built with GCC 4.8.4 and as 2.24 using: 654 // gcc -Wa,--compress-debug-sections -g -c -o zdebug-test-gcc484-x86-64.obj hello.c 655 f, err := Open("testdata/zdebug-test-gcc484-x86-64.obj") 656 if err != nil { 657 t.Fatal(err) 658 } 659 dwarf, err := f.DWARF() 660 if err != nil { 661 t.Fatal(err) 662 } 663 reader := dwarf.Reader() 664 n := 0 665 for { 666 entry, err := reader.Next() 667 if err != nil { 668 t.Fatal(err) 669 } 670 if entry == nil { 671 break 672 } 673 n++ 674 } 675 if n != 18 { 676 t.Fatalf("want %d DWARF entries, got %d", 18, n) 677 } 678 } 679 680 func TestCompressedSection(t *testing.T) { 681 // Test files built with gcc -g -S hello.c and assembled with 682 // --compress-debug-sections=zlib-gabi. 683 f, err := Open("testdata/compressed-64.obj") 684 if err != nil { 685 t.Fatal(err) 686 } 687 sec := f.Section(".debug_info") 688 wantData := []byte{ 689 182, 0, 0, 0, 4, 0, 0, 0, 0, 0, 8, 1, 0, 0, 0, 0, 690 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 691 0, 27, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 8, 7, 692 0, 0, 0, 0, 2, 1, 8, 0, 0, 0, 0, 2, 2, 7, 0, 0, 693 0, 0, 2, 4, 7, 0, 0, 0, 0, 2, 1, 6, 0, 0, 0, 0, 694 2, 2, 5, 0, 0, 0, 0, 3, 4, 5, 105, 110, 116, 0, 2, 8, 695 5, 0, 0, 0, 0, 2, 8, 7, 0, 0, 0, 0, 4, 8, 114, 0, 696 0, 0, 2, 1, 6, 0, 0, 0, 0, 5, 0, 0, 0, 0, 1, 4, 697 0, 0, 0, 0, 0, 0, 0, 0, 27, 0, 0, 0, 0, 0, 0, 0, 698 1, 156, 179, 0, 0, 0, 6, 0, 0, 0, 0, 1, 4, 87, 0, 0, 699 0, 2, 145, 108, 6, 0, 0, 0, 0, 1, 4, 179, 0, 0, 0, 2, 700 145, 96, 0, 4, 8, 108, 0, 0, 0, 0, 701 } 702 703 // Test Data method. 704 b, err := sec.Data() 705 if err != nil { 706 t.Fatal(err) 707 } 708 if !bytes.Equal(wantData, b) { 709 t.Fatalf("want data %x, got %x", wantData, b) 710 } 711 712 // Test Open method and seeking. 713 buf, have, count := make([]byte, len(b)), make([]bool, len(b)), 0 714 sf := sec.Open() 715 if got, err := sf.Seek(0, io.SeekEnd); got != int64(len(b)) || err != nil { 716 t.Fatalf("want seek end %d, got %d error %v", len(b), got, err) 717 } 718 if n, err := sf.Read(buf); n != 0 || err != io.EOF { 719 t.Fatalf("want EOF with 0 bytes, got %v with %d bytes", err, n) 720 } 721 pos := int64(len(buf)) 722 for count < len(buf) { 723 // Construct random seek arguments. 724 whence := rand.Intn(3) 725 target := rand.Int63n(int64(len(buf))) 726 var offset int64 727 switch whence { 728 case io.SeekStart: 729 offset = target 730 case io.SeekCurrent: 731 offset = target - pos 732 case io.SeekEnd: 733 offset = target - int64(len(buf)) 734 } 735 pos, err = sf.Seek(offset, whence) 736 if err != nil { 737 t.Fatal(err) 738 } 739 if pos != target { 740 t.Fatalf("want position %d, got %d", target, pos) 741 } 742 743 // Read data from the new position. 744 end := pos + 16 745 if end > int64(len(buf)) { 746 end = int64(len(buf)) 747 } 748 n, err := io.ReadFull(sf, buf[pos:end]) 749 if err != nil { 750 t.Fatal(err) 751 } 752 for i := 0; i < n; i++ { 753 if !have[pos] { 754 have[pos] = true 755 count++ 756 } 757 pos++ 758 } 759 } 760 if !bytes.Equal(wantData, buf) { 761 t.Fatalf("want data %x, got %x", wantData, buf) 762 } 763 } 764 765 func TestNoSectionOverlaps(t *testing.T) { 766 // Ensure 6l outputs sections without overlaps. 767 if runtime.GOOS != "linux" && runtime.GOOS != "freebsd" { 768 return // not ELF 769 } 770 _ = net.ResolveIPAddr // force dynamic linkage 771 f, err := Open(os.Args[0]) 772 if err != nil { 773 t.Error(err) 774 return 775 } 776 for i, si := range f.Sections { 777 sih := si.SectionHeader 778 if sih.Type == SHT_NOBITS { 779 continue 780 } 781 for j, sj := range f.Sections { 782 sjh := sj.SectionHeader 783 if i == j || sjh.Type == SHT_NOBITS || sih.Offset == sjh.Offset && sih.Size == 0 { 784 continue 785 } 786 if sih.Offset >= sjh.Offset && sih.Offset < sjh.Offset+sjh.Size { 787 t.Errorf("ld produced ELF with section %s within %s: 0x%x <= 0x%x..0x%x < 0x%x", 788 sih.Name, sjh.Name, sjh.Offset, sih.Offset, sih.Offset+sih.Size, sjh.Offset+sjh.Size) 789 } 790 } 791 } 792 }