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-gcc720-riscv64.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: "GNU C11 7.2.0 -march=rv64imafdc -mabi=lp64d -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(0x2c), Class: dwarf.ClassAddress}, 584 {Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr}, 585 }, 586 }}, 587 }, 588 }, 589 { 590 "testdata/go-relocation-test-clang-x86.obj", 591 []relocationTestEntry{ 592 {0, &dwarf.Entry{ 593 Offset: 0xb, 594 Tag: dwarf.TagCompileUnit, 595 Children: true, 596 Field: []dwarf.Field{ 597 {Attr: dwarf.AttrProducer, Val: "clang version google3-trunk (trunk r209387)", Class: dwarf.ClassString}, 598 {Attr: dwarf.AttrLanguage, Val: int64(12), Class: dwarf.ClassConstant}, 599 {Attr: dwarf.AttrName, Val: "go-relocation-test-clang.c", Class: dwarf.ClassString}, 600 {Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr}, 601 {Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString}, 602 }, 603 }}, 604 }, 605 }, 606 { 607 "testdata/gcc-amd64-openbsd-debug-with-rela.obj", 608 []relocationTestEntry{ 609 {203, &dwarf.Entry{ 610 Offset: 0xc62, 611 Tag: dwarf.TagMember, 612 Children: false, 613 Field: []dwarf.Field{ 614 {Attr: dwarf.AttrName, Val: "it_interval", Class: dwarf.ClassString}, 615 {Attr: dwarf.AttrDeclFile, Val: int64(7), Class: dwarf.ClassConstant}, 616 {Attr: dwarf.AttrDeclLine, Val: int64(236), Class: dwarf.ClassConstant}, 617 {Attr: dwarf.AttrType, Val: dwarf.Offset(0xb7f), Class: dwarf.ClassReference}, 618 {Attr: dwarf.AttrDataMemberLoc, Val: []byte{0x23, 0x0}, Class: dwarf.ClassExprLoc}, 619 }, 620 }}, 621 {204, &dwarf.Entry{ 622 Offset: 0xc70, 623 Tag: dwarf.TagMember, 624 Children: false, 625 Field: []dwarf.Field{ 626 {Attr: dwarf.AttrName, Val: "it_value", Class: dwarf.ClassString}, 627 {Attr: dwarf.AttrDeclFile, Val: int64(7), Class: dwarf.ClassConstant}, 628 {Attr: dwarf.AttrDeclLine, Val: int64(237), Class: dwarf.ClassConstant}, 629 {Attr: dwarf.AttrType, Val: dwarf.Offset(0xb7f), Class: dwarf.ClassReference}, 630 {Attr: dwarf.AttrDataMemberLoc, Val: []byte{0x23, 0x10}, Class: dwarf.ClassExprLoc}, 631 }, 632 }}, 633 }, 634 }, 635 } 636 637 func TestDWARFRelocations(t *testing.T) { 638 for i, test := range relocationTests { 639 f, err := Open(test.file) 640 if err != nil { 641 t.Error(err) 642 continue 643 } 644 dwarf, err := f.DWARF() 645 if err != nil { 646 t.Error(err) 647 continue 648 } 649 for _, testEntry := range test.entries { 650 reader := dwarf.Reader() 651 for j := 0; j < testEntry.entryNumber; j++ { 652 entry, err := reader.Next() 653 if entry == nil || err != nil { 654 t.Errorf("Failed to skip to entry %d: %v", testEntry.entryNumber, err) 655 continue 656 } 657 } 658 entry, err := reader.Next() 659 if err != nil { 660 t.Error(err) 661 continue 662 } 663 if !reflect.DeepEqual(testEntry.entry, entry) { 664 t.Errorf("#%d/%d: mismatch: got:%#v want:%#v", i, testEntry.entryNumber, entry, testEntry.entry) 665 continue 666 } 667 } 668 } 669 } 670 671 func TestCompressedDWARF(t *testing.T) { 672 // Test file built with GCC 4.8.4 and as 2.24 using: 673 // gcc -Wa,--compress-debug-sections -g -c -o zdebug-test-gcc484-x86-64.obj hello.c 674 f, err := Open("testdata/zdebug-test-gcc484-x86-64.obj") 675 if err != nil { 676 t.Fatal(err) 677 } 678 dwarf, err := f.DWARF() 679 if err != nil { 680 t.Fatal(err) 681 } 682 reader := dwarf.Reader() 683 n := 0 684 for { 685 entry, err := reader.Next() 686 if err != nil { 687 t.Fatal(err) 688 } 689 if entry == nil { 690 break 691 } 692 n++ 693 } 694 if n != 18 { 695 t.Fatalf("want %d DWARF entries, got %d", 18, n) 696 } 697 } 698 699 func TestCompressedSection(t *testing.T) { 700 // Test files built with gcc -g -S hello.c and assembled with 701 // --compress-debug-sections=zlib-gabi. 702 f, err := Open("testdata/compressed-64.obj") 703 if err != nil { 704 t.Fatal(err) 705 } 706 sec := f.Section(".debug_info") 707 wantData := []byte{ 708 182, 0, 0, 0, 4, 0, 0, 0, 0, 0, 8, 1, 0, 0, 0, 0, 709 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 710 0, 27, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 8, 7, 711 0, 0, 0, 0, 2, 1, 8, 0, 0, 0, 0, 2, 2, 7, 0, 0, 712 0, 0, 2, 4, 7, 0, 0, 0, 0, 2, 1, 6, 0, 0, 0, 0, 713 2, 2, 5, 0, 0, 0, 0, 3, 4, 5, 105, 110, 116, 0, 2, 8, 714 5, 0, 0, 0, 0, 2, 8, 7, 0, 0, 0, 0, 4, 8, 114, 0, 715 0, 0, 2, 1, 6, 0, 0, 0, 0, 5, 0, 0, 0, 0, 1, 4, 716 0, 0, 0, 0, 0, 0, 0, 0, 27, 0, 0, 0, 0, 0, 0, 0, 717 1, 156, 179, 0, 0, 0, 6, 0, 0, 0, 0, 1, 4, 87, 0, 0, 718 0, 2, 145, 108, 6, 0, 0, 0, 0, 1, 4, 179, 0, 0, 0, 2, 719 145, 96, 0, 4, 8, 108, 0, 0, 0, 0, 720 } 721 722 // Test Data method. 723 b, err := sec.Data() 724 if err != nil { 725 t.Fatal(err) 726 } 727 if !bytes.Equal(wantData, b) { 728 t.Fatalf("want data %x, got %x", wantData, b) 729 } 730 731 // Test Open method and seeking. 732 buf, have, count := make([]byte, len(b)), make([]bool, len(b)), 0 733 sf := sec.Open() 734 if got, err := sf.Seek(0, io.SeekEnd); got != int64(len(b)) || err != nil { 735 t.Fatalf("want seek end %d, got %d error %v", len(b), got, err) 736 } 737 if n, err := sf.Read(buf); n != 0 || err != io.EOF { 738 t.Fatalf("want EOF with 0 bytes, got %v with %d bytes", err, n) 739 } 740 pos := int64(len(buf)) 741 for count < len(buf) { 742 // Construct random seek arguments. 743 whence := rand.Intn(3) 744 target := rand.Int63n(int64(len(buf))) 745 var offset int64 746 switch whence { 747 case io.SeekStart: 748 offset = target 749 case io.SeekCurrent: 750 offset = target - pos 751 case io.SeekEnd: 752 offset = target - int64(len(buf)) 753 } 754 pos, err = sf.Seek(offset, whence) 755 if err != nil { 756 t.Fatal(err) 757 } 758 if pos != target { 759 t.Fatalf("want position %d, got %d", target, pos) 760 } 761 762 // Read data from the new position. 763 end := pos + 16 764 if end > int64(len(buf)) { 765 end = int64(len(buf)) 766 } 767 n, err := io.ReadFull(sf, buf[pos:end]) 768 if err != nil { 769 t.Fatal(err) 770 } 771 for i := 0; i < n; i++ { 772 if !have[pos] { 773 have[pos] = true 774 count++ 775 } 776 pos++ 777 } 778 } 779 if !bytes.Equal(wantData, buf) { 780 t.Fatalf("want data %x, got %x", wantData, buf) 781 } 782 } 783 784 func TestNoSectionOverlaps(t *testing.T) { 785 // Ensure cmd/link outputs sections without overlaps. 786 switch runtime.GOOS { 787 case "aix", "android", "darwin", "js", "nacl", "plan9", "windows": 788 t.Skipf("cmd/link doesn't produce ELF binaries on %s", runtime.GOOS) 789 } 790 _ = net.ResolveIPAddr // force dynamic linkage 791 f, err := Open(os.Args[0]) 792 if err != nil { 793 t.Error(err) 794 return 795 } 796 for i, si := range f.Sections { 797 sih := si.SectionHeader 798 if sih.Type == SHT_NOBITS { 799 continue 800 } 801 for j, sj := range f.Sections { 802 sjh := sj.SectionHeader 803 if i == j || sjh.Type == SHT_NOBITS || sih.Offset == sjh.Offset && sih.Size == 0 { 804 continue 805 } 806 if sih.Offset >= sjh.Offset && sih.Offset < sjh.Offset+sjh.Size { 807 t.Errorf("ld produced ELF with section %s within %s: 0x%x <= 0x%x..0x%x < 0x%x", 808 sih.Name, sjh.Name, sjh.Offset, sih.Offset, sih.Offset+sih.Size, sjh.Offset+sjh.Size) 809 } 810 } 811 } 812 } 813 814 func TestIssue10996(t *testing.T) { 815 data := []byte("\u007fELF\x02\x01\x010000000000000" + 816 "\x010000000000000000000" + 817 "\x00\x00\x00\x00\x00\x00\x00\x0000000000\x00\x00\x00\x00" + 818 "0000") 819 _, err := NewFile(bytes.NewReader(data)) 820 if err == nil { 821 t.Fatalf("opening invalid ELF file unexpectedly suceeded") 822 } 823 } 824
View as plain text