github.com/dannin/go@v0.0.0-20161031215817-d35dfd405eaa/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-gcc493-mips64le.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.3 -mel -mabi=64 -mllsc -mno-shared -g -fstack-protector-strong", 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(100), Class: dwarf.ClassConstant}, 527 {Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr}, 528 }, 529 }}, 530 }, 531 }, 532 { 533 "testdata/go-relocation-test-clang-x86.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: "clang version google3-trunk (trunk r209387)", Class: dwarf.ClassString}, 541 {Attr: dwarf.AttrLanguage, Val: int64(12), Class: dwarf.ClassConstant}, 542 {Attr: dwarf.AttrName, Val: "go-relocation-test-clang.c", Class: dwarf.ClassString}, 543 {Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr}, 544 {Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString}, 545 }, 546 }}, 547 }, 548 }, 549 { 550 "testdata/gcc-amd64-openbsd-debug-with-rela.obj", 551 []relocationTestEntry{ 552 {203, &dwarf.Entry{ 553 Offset: 0xc62, 554 Tag: dwarf.TagMember, 555 Children: false, 556 Field: []dwarf.Field{ 557 {Attr: dwarf.AttrName, Val: "it_interval", Class: dwarf.ClassString}, 558 {Attr: dwarf.AttrDeclFile, Val: int64(7), Class: dwarf.ClassConstant}, 559 {Attr: dwarf.AttrDeclLine, Val: int64(236), Class: dwarf.ClassConstant}, 560 {Attr: dwarf.AttrType, Val: dwarf.Offset(0xb7f), Class: dwarf.ClassReference}, 561 {Attr: dwarf.AttrDataMemberLoc, Val: []byte{0x23, 0x0}, Class: dwarf.ClassExprLoc}, 562 }, 563 }}, 564 {204, &dwarf.Entry{ 565 Offset: 0xc70, 566 Tag: dwarf.TagMember, 567 Children: false, 568 Field: []dwarf.Field{ 569 {Attr: dwarf.AttrName, Val: "it_value", Class: dwarf.ClassString}, 570 {Attr: dwarf.AttrDeclFile, Val: int64(7), Class: dwarf.ClassConstant}, 571 {Attr: dwarf.AttrDeclLine, Val: int64(237), Class: dwarf.ClassConstant}, 572 {Attr: dwarf.AttrType, Val: dwarf.Offset(0xb7f), Class: dwarf.ClassReference}, 573 {Attr: dwarf.AttrDataMemberLoc, Val: []byte{0x23, 0x10}, Class: dwarf.ClassExprLoc}, 574 }, 575 }}, 576 }, 577 }, 578 } 579 580 func TestDWARFRelocations(t *testing.T) { 581 for i, test := range relocationTests { 582 f, err := Open(test.file) 583 if err != nil { 584 t.Error(err) 585 continue 586 } 587 dwarf, err := f.DWARF() 588 if err != nil { 589 t.Error(err) 590 continue 591 } 592 for _, testEntry := range test.entries { 593 reader := dwarf.Reader() 594 for j := 0; j < testEntry.entryNumber; j++ { 595 entry, err := reader.Next() 596 if entry == nil || err != nil { 597 t.Errorf("Failed to skip to entry %d: %v", testEntry.entryNumber, err) 598 continue 599 } 600 } 601 entry, err := reader.Next() 602 if err != nil { 603 t.Error(err) 604 continue 605 } 606 if !reflect.DeepEqual(testEntry.entry, entry) { 607 t.Errorf("#%d/%d: mismatch: got:%#v want:%#v", i, testEntry.entryNumber, entry, testEntry.entry) 608 continue 609 } 610 } 611 } 612 } 613 614 func TestCompressedDWARF(t *testing.T) { 615 // Test file built with GCC 4.8.4 and as 2.24 using: 616 // gcc -Wa,--compress-debug-sections -g -c -o zdebug-test-gcc484-x86-64.obj hello.c 617 f, err := Open("testdata/zdebug-test-gcc484-x86-64.obj") 618 if err != nil { 619 t.Fatal(err) 620 } 621 dwarf, err := f.DWARF() 622 if err != nil { 623 t.Fatal(err) 624 } 625 reader := dwarf.Reader() 626 n := 0 627 for { 628 entry, err := reader.Next() 629 if err != nil { 630 t.Fatal(err) 631 } 632 if entry == nil { 633 break 634 } 635 n++ 636 } 637 if n != 18 { 638 t.Fatalf("want %d DWARF entries, got %d", 18, n) 639 } 640 } 641 642 func TestCompressedSection(t *testing.T) { 643 // Test files built with gcc -g -S hello.c and assembled with 644 // --compress-debug-sections=zlib-gabi. 645 f, err := Open("testdata/compressed-64.obj") 646 if err != nil { 647 t.Fatal(err) 648 } 649 sec := f.Section(".debug_info") 650 wantData := []byte{ 651 182, 0, 0, 0, 4, 0, 0, 0, 0, 0, 8, 1, 0, 0, 0, 0, 652 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 653 0, 27, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 8, 7, 654 0, 0, 0, 0, 2, 1, 8, 0, 0, 0, 0, 2, 2, 7, 0, 0, 655 0, 0, 2, 4, 7, 0, 0, 0, 0, 2, 1, 6, 0, 0, 0, 0, 656 2, 2, 5, 0, 0, 0, 0, 3, 4, 5, 105, 110, 116, 0, 2, 8, 657 5, 0, 0, 0, 0, 2, 8, 7, 0, 0, 0, 0, 4, 8, 114, 0, 658 0, 0, 2, 1, 6, 0, 0, 0, 0, 5, 0, 0, 0, 0, 1, 4, 659 0, 0, 0, 0, 0, 0, 0, 0, 27, 0, 0, 0, 0, 0, 0, 0, 660 1, 156, 179, 0, 0, 0, 6, 0, 0, 0, 0, 1, 4, 87, 0, 0, 661 0, 2, 145, 108, 6, 0, 0, 0, 0, 1, 4, 179, 0, 0, 0, 2, 662 145, 96, 0, 4, 8, 108, 0, 0, 0, 0, 663 } 664 665 // Test Data method. 666 b, err := sec.Data() 667 if err != nil { 668 t.Fatal(err) 669 } 670 if !bytes.Equal(wantData, b) { 671 t.Fatalf("want data %x, got %x", wantData, b) 672 } 673 674 // Test Open method and seeking. 675 buf, have, count := make([]byte, len(b)), make([]bool, len(b)), 0 676 sf := sec.Open() 677 if got, err := sf.Seek(0, io.SeekEnd); got != int64(len(b)) || err != nil { 678 t.Fatalf("want seek end %d, got %d error %v", len(b), got, err) 679 } 680 if n, err := sf.Read(buf); n != 0 || err != io.EOF { 681 t.Fatalf("want EOF with 0 bytes, got %v with %d bytes", err, n) 682 } 683 pos := int64(len(buf)) 684 for count < len(buf) { 685 // Construct random seek arguments. 686 whence := rand.Intn(3) 687 target := rand.Int63n(int64(len(buf))) 688 var offset int64 689 switch whence { 690 case io.SeekStart: 691 offset = target 692 case io.SeekCurrent: 693 offset = target - pos 694 case io.SeekEnd: 695 offset = target - int64(len(buf)) 696 } 697 pos, err = sf.Seek(offset, whence) 698 if err != nil { 699 t.Fatal(err) 700 } 701 if pos != target { 702 t.Fatalf("want position %d, got %d", target, pos) 703 } 704 705 // Read data from the new position. 706 end := pos + 16 707 if end > int64(len(buf)) { 708 end = int64(len(buf)) 709 } 710 n, err := io.ReadFull(sf, buf[pos:end]) 711 if err != nil { 712 t.Fatal(err) 713 } 714 for i := 0; i < n; i++ { 715 if !have[pos] { 716 have[pos] = true 717 count++ 718 } 719 pos++ 720 } 721 } 722 if !bytes.Equal(wantData, buf) { 723 t.Fatalf("want data %x, got %x", wantData, buf) 724 } 725 } 726 727 func TestNoSectionOverlaps(t *testing.T) { 728 // Ensure 6l outputs sections without overlaps. 729 if runtime.GOOS != "linux" && runtime.GOOS != "freebsd" { 730 return // not ELF 731 } 732 _ = net.ResolveIPAddr // force dynamic linkage 733 f, err := Open(os.Args[0]) 734 if err != nil { 735 t.Error(err) 736 return 737 } 738 for i, si := range f.Sections { 739 sih := si.SectionHeader 740 if sih.Type == SHT_NOBITS { 741 continue 742 } 743 for j, sj := range f.Sections { 744 sjh := sj.SectionHeader 745 if i == j || sjh.Type == SHT_NOBITS || sih.Offset == sjh.Offset && sih.Size == 0 { 746 continue 747 } 748 if sih.Offset >= sjh.Offset && sih.Offset < sjh.Offset+sjh.Size { 749 t.Errorf("ld produced ELF with section %s within %s: 0x%x <= 0x%x..0x%x < 0x%x", 750 sih.Name, sjh.Name, sjh.Offset, sih.Offset, sih.Offset+sih.Size, sjh.Offset+sjh.Size) 751 } 752 } 753 } 754 }