1 |
747 |
jeremybenn |
// 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 macho
|
6 |
|
|
|
7 |
|
|
import (
|
8 |
|
|
"reflect"
|
9 |
|
|
"testing"
|
10 |
|
|
)
|
11 |
|
|
|
12 |
|
|
type fileTest struct {
|
13 |
|
|
file string
|
14 |
|
|
hdr FileHeader
|
15 |
|
|
segments []*SegmentHeader
|
16 |
|
|
sections []*SectionHeader
|
17 |
|
|
}
|
18 |
|
|
|
19 |
|
|
var fileTests = []fileTest{
|
20 |
|
|
{
|
21 |
|
|
"testdata/gcc-386-darwin-exec",
|
22 |
|
|
FileHeader{0xfeedface, Cpu386, 0x3, 0x2, 0xc, 0x3c0, 0x85},
|
23 |
|
|
[]*SegmentHeader{
|
24 |
|
|
{LoadCmdSegment, 0x38, "__PAGEZERO", 0x0, 0x1000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
|
25 |
|
|
{LoadCmdSegment, 0xc0, "__TEXT", 0x1000, 0x1000, 0x0, 0x1000, 0x7, 0x5, 0x2, 0x0},
|
26 |
|
|
{LoadCmdSegment, 0xc0, "__DATA", 0x2000, 0x1000, 0x1000, 0x1000, 0x7, 0x3, 0x2, 0x0},
|
27 |
|
|
{LoadCmdSegment, 0x7c, "__IMPORT", 0x3000, 0x1000, 0x2000, 0x1000, 0x7, 0x7, 0x1, 0x0},
|
28 |
|
|
{LoadCmdSegment, 0x38, "__LINKEDIT", 0x4000, 0x1000, 0x3000, 0x12c, 0x7, 0x1, 0x0, 0x0},
|
29 |
|
|
nil,
|
30 |
|
|
nil,
|
31 |
|
|
nil,
|
32 |
|
|
nil,
|
33 |
|
|
nil,
|
34 |
|
|
nil,
|
35 |
|
|
nil,
|
36 |
|
|
},
|
37 |
|
|
[]*SectionHeader{
|
38 |
|
|
{"__text", "__TEXT", 0x1f68, 0x88, 0xf68, 0x2, 0x0, 0x0, 0x80000400},
|
39 |
|
|
{"__cstring", "__TEXT", 0x1ff0, 0xd, 0xff0, 0x0, 0x0, 0x0, 0x2},
|
40 |
|
|
{"__data", "__DATA", 0x2000, 0x14, 0x1000, 0x2, 0x0, 0x0, 0x0},
|
41 |
|
|
{"__dyld", "__DATA", 0x2014, 0x1c, 0x1014, 0x2, 0x0, 0x0, 0x0},
|
42 |
|
|
{"__jump_table", "__IMPORT", 0x3000, 0xa, 0x2000, 0x6, 0x0, 0x0, 0x4000008},
|
43 |
|
|
},
|
44 |
|
|
},
|
45 |
|
|
{
|
46 |
|
|
"testdata/gcc-amd64-darwin-exec",
|
47 |
|
|
FileHeader{0xfeedfacf, CpuAmd64, 0x80000003, 0x2, 0xb, 0x568, 0x85},
|
48 |
|
|
[]*SegmentHeader{
|
49 |
|
|
{LoadCmdSegment64, 0x48, "__PAGEZERO", 0x0, 0x100000000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
|
50 |
|
|
{LoadCmdSegment64, 0x1d8, "__TEXT", 0x100000000, 0x1000, 0x0, 0x1000, 0x7, 0x5, 0x5, 0x0},
|
51 |
|
|
{LoadCmdSegment64, 0x138, "__DATA", 0x100001000, 0x1000, 0x1000, 0x1000, 0x7, 0x3, 0x3, 0x0},
|
52 |
|
|
{LoadCmdSegment64, 0x48, "__LINKEDIT", 0x100002000, 0x1000, 0x2000, 0x140, 0x7, 0x1, 0x0, 0x0},
|
53 |
|
|
nil,
|
54 |
|
|
nil,
|
55 |
|
|
nil,
|
56 |
|
|
nil,
|
57 |
|
|
nil,
|
58 |
|
|
nil,
|
59 |
|
|
nil,
|
60 |
|
|
},
|
61 |
|
|
[]*SectionHeader{
|
62 |
|
|
{"__text", "__TEXT", 0x100000f14, 0x6d, 0xf14, 0x2, 0x0, 0x0, 0x80000400},
|
63 |
|
|
{"__symbol_stub1", "__TEXT", 0x100000f81, 0xc, 0xf81, 0x0, 0x0, 0x0, 0x80000408},
|
64 |
|
|
{"__stub_helper", "__TEXT", 0x100000f90, 0x18, 0xf90, 0x2, 0x0, 0x0, 0x0},
|
65 |
|
|
{"__cstring", "__TEXT", 0x100000fa8, 0xd, 0xfa8, 0x0, 0x0, 0x0, 0x2},
|
66 |
|
|
{"__eh_frame", "__TEXT", 0x100000fb8, 0x48, 0xfb8, 0x3, 0x0, 0x0, 0x6000000b},
|
67 |
|
|
{"__data", "__DATA", 0x100001000, 0x1c, 0x1000, 0x3, 0x0, 0x0, 0x0},
|
68 |
|
|
{"__dyld", "__DATA", 0x100001020, 0x38, 0x1020, 0x3, 0x0, 0x0, 0x0},
|
69 |
|
|
{"__la_symbol_ptr", "__DATA", 0x100001058, 0x10, 0x1058, 0x2, 0x0, 0x0, 0x7},
|
70 |
|
|
},
|
71 |
|
|
},
|
72 |
|
|
{
|
73 |
|
|
"testdata/gcc-amd64-darwin-exec-debug",
|
74 |
|
|
FileHeader{0xfeedfacf, CpuAmd64, 0x80000003, 0xa, 0x4, 0x5a0, 0},
|
75 |
|
|
[]*SegmentHeader{
|
76 |
|
|
nil,
|
77 |
|
|
{LoadCmdSegment64, 0x1d8, "__TEXT", 0x100000000, 0x1000, 0x0, 0x0, 0x7, 0x5, 0x5, 0x0},
|
78 |
|
|
{LoadCmdSegment64, 0x138, "__DATA", 0x100001000, 0x1000, 0x0, 0x0, 0x7, 0x3, 0x3, 0x0},
|
79 |
|
|
{LoadCmdSegment64, 0x278, "__DWARF", 0x100002000, 0x1000, 0x1000, 0x1bc, 0x7, 0x3, 0x7, 0x0},
|
80 |
|
|
},
|
81 |
|
|
[]*SectionHeader{
|
82 |
|
|
{"__text", "__TEXT", 0x100000f14, 0x0, 0x0, 0x2, 0x0, 0x0, 0x80000400},
|
83 |
|
|
{"__symbol_stub1", "__TEXT", 0x100000f81, 0x0, 0x0, 0x0, 0x0, 0x0, 0x80000408},
|
84 |
|
|
{"__stub_helper", "__TEXT", 0x100000f90, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0},
|
85 |
|
|
{"__cstring", "__TEXT", 0x100000fa8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2},
|
86 |
|
|
{"__eh_frame", "__TEXT", 0x100000fb8, 0x0, 0x0, 0x3, 0x0, 0x0, 0x6000000b},
|
87 |
|
|
{"__data", "__DATA", 0x100001000, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0},
|
88 |
|
|
{"__dyld", "__DATA", 0x100001020, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0},
|
89 |
|
|
{"__la_symbol_ptr", "__DATA", 0x100001058, 0x0, 0x0, 0x2, 0x0, 0x0, 0x7},
|
90 |
|
|
{"__debug_abbrev", "__DWARF", 0x100002000, 0x36, 0x1000, 0x0, 0x0, 0x0, 0x0},
|
91 |
|
|
{"__debug_aranges", "__DWARF", 0x100002036, 0x30, 0x1036, 0x0, 0x0, 0x0, 0x0},
|
92 |
|
|
{"__debug_frame", "__DWARF", 0x100002066, 0x40, 0x1066, 0x0, 0x0, 0x0, 0x0},
|
93 |
|
|
{"__debug_info", "__DWARF", 0x1000020a6, 0x54, 0x10a6, 0x0, 0x0, 0x0, 0x0},
|
94 |
|
|
{"__debug_line", "__DWARF", 0x1000020fa, 0x47, 0x10fa, 0x0, 0x0, 0x0, 0x0},
|
95 |
|
|
{"__debug_pubnames", "__DWARF", 0x100002141, 0x1b, 0x1141, 0x0, 0x0, 0x0, 0x0},
|
96 |
|
|
{"__debug_str", "__DWARF", 0x10000215c, 0x60, 0x115c, 0x0, 0x0, 0x0, 0x0},
|
97 |
|
|
},
|
98 |
|
|
},
|
99 |
|
|
}
|
100 |
|
|
|
101 |
|
|
func TestOpen(t *testing.T) {
|
102 |
|
|
for i := range fileTests {
|
103 |
|
|
tt := &fileTests[i]
|
104 |
|
|
|
105 |
|
|
f, err := Open(tt.file)
|
106 |
|
|
if err != nil {
|
107 |
|
|
t.Error(err)
|
108 |
|
|
continue
|
109 |
|
|
}
|
110 |
|
|
if !reflect.DeepEqual(f.FileHeader, tt.hdr) {
|
111 |
|
|
t.Errorf("open %s:\n\thave %#v\n\twant %#v\n", tt.file, f.FileHeader, tt.hdr)
|
112 |
|
|
continue
|
113 |
|
|
}
|
114 |
|
|
for i, l := range f.Loads {
|
115 |
|
|
if i >= len(tt.segments) {
|
116 |
|
|
break
|
117 |
|
|
}
|
118 |
|
|
sh := tt.segments[i]
|
119 |
|
|
s, ok := l.(*Segment)
|
120 |
|
|
if sh == nil {
|
121 |
|
|
if ok {
|
122 |
|
|
t.Errorf("open %s, section %d: skipping %#v\n", tt.file, i, &s.SegmentHeader)
|
123 |
|
|
}
|
124 |
|
|
continue
|
125 |
|
|
}
|
126 |
|
|
if !ok {
|
127 |
|
|
t.Errorf("open %s, section %d: not *Segment\n", tt.file, i)
|
128 |
|
|
continue
|
129 |
|
|
}
|
130 |
|
|
have := &s.SegmentHeader
|
131 |
|
|
want := sh
|
132 |
|
|
if !reflect.DeepEqual(have, want) {
|
133 |
|
|
t.Errorf("open %s, segment %d:\n\thave %#v\n\twant %#v\n", tt.file, i, have, want)
|
134 |
|
|
}
|
135 |
|
|
}
|
136 |
|
|
tn := len(tt.segments)
|
137 |
|
|
fn := len(f.Loads)
|
138 |
|
|
if tn != fn {
|
139 |
|
|
t.Errorf("open %s: len(Loads) = %d, want %d", tt.file, fn, tn)
|
140 |
|
|
}
|
141 |
|
|
|
142 |
|
|
for i, sh := range f.Sections {
|
143 |
|
|
if i >= len(tt.sections) {
|
144 |
|
|
break
|
145 |
|
|
}
|
146 |
|
|
have := &sh.SectionHeader
|
147 |
|
|
want := tt.sections[i]
|
148 |
|
|
if !reflect.DeepEqual(have, want) {
|
149 |
|
|
t.Errorf("open %s, section %d:\n\thave %#v\n\twant %#v\n", tt.file, i, have, want)
|
150 |
|
|
}
|
151 |
|
|
}
|
152 |
|
|
tn = len(tt.sections)
|
153 |
|
|
fn = len(f.Sections)
|
154 |
|
|
if tn != fn {
|
155 |
|
|
t.Errorf("open %s: len(Sections) = %d, want %d", tt.file, fn, tn)
|
156 |
|
|
}
|
157 |
|
|
|
158 |
|
|
}
|
159 |
|
|
}
|
160 |
|
|
|
161 |
|
|
func TestOpenFailure(t *testing.T) {
|
162 |
|
|
filename := "file.go" // not a Mach-O file
|
163 |
|
|
_, err := Open(filename) // don't crash
|
164 |
|
|
if err == nil {
|
165 |
|
|
t.Errorf("open %s: succeeded unexpectedly", filename)
|
166 |
|
|
}
|
167 |
|
|
}
|