xref: /aosp_15_r20/build/soong/elf/elf_test.go (revision 333d2b3687b3a337dbcca9d65000bca186795e39)
1*333d2b36SAndroid Build Coastguard Worker// Copyright 2022 Google Inc. All rights reserved.
2*333d2b36SAndroid Build Coastguard Worker//
3*333d2b36SAndroid Build Coastguard Worker// Licensed under the Apache License, Version 2.0 (the "License");
4*333d2b36SAndroid Build Coastguard Worker// you may not use this file except in compliance with the License.
5*333d2b36SAndroid Build Coastguard Worker// You may obtain a copy of the License at
6*333d2b36SAndroid Build Coastguard Worker//
7*333d2b36SAndroid Build Coastguard Worker//     http://www.apache.org/licenses/LICENSE-2.0
8*333d2b36SAndroid Build Coastguard Worker//
9*333d2b36SAndroid Build Coastguard Worker// Unless required by applicable law or agreed to in writing, software
10*333d2b36SAndroid Build Coastguard Worker// distributed under the License is distributed on an "AS IS" BASIS,
11*333d2b36SAndroid Build Coastguard Worker// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*333d2b36SAndroid Build Coastguard Worker// See the License for the specific language governing permissions and
13*333d2b36SAndroid Build Coastguard Worker// limitations under the License.
14*333d2b36SAndroid Build Coastguard Worker
15*333d2b36SAndroid Build Coastguard Workerpackage elf
16*333d2b36SAndroid Build Coastguard Worker
17*333d2b36SAndroid Build Coastguard Workerimport (
18*333d2b36SAndroid Build Coastguard Worker	"bytes"
19*333d2b36SAndroid Build Coastguard Worker	"debug/elf"
20*333d2b36SAndroid Build Coastguard Worker	"encoding/binary"
21*333d2b36SAndroid Build Coastguard Worker	"reflect"
22*333d2b36SAndroid Build Coastguard Worker	"testing"
23*333d2b36SAndroid Build Coastguard Worker)
24*333d2b36SAndroid Build Coastguard Worker
25*333d2b36SAndroid Build Coastguard Workerfunc Test_elfIdentifierFromReaderAt_BadElfFile(t *testing.T) {
26*333d2b36SAndroid Build Coastguard Worker	tests := []struct {
27*333d2b36SAndroid Build Coastguard Worker		name     string
28*333d2b36SAndroid Build Coastguard Worker		contents string
29*333d2b36SAndroid Build Coastguard Worker	}{
30*333d2b36SAndroid Build Coastguard Worker		{
31*333d2b36SAndroid Build Coastguard Worker			name:     "empty",
32*333d2b36SAndroid Build Coastguard Worker			contents: "",
33*333d2b36SAndroid Build Coastguard Worker		},
34*333d2b36SAndroid Build Coastguard Worker		{
35*333d2b36SAndroid Build Coastguard Worker			name:     "text",
36*333d2b36SAndroid Build Coastguard Worker			contents: "#!/bin/bash\necho foobar",
37*333d2b36SAndroid Build Coastguard Worker		},
38*333d2b36SAndroid Build Coastguard Worker		{
39*333d2b36SAndroid Build Coastguard Worker			name:     "empty elf",
40*333d2b36SAndroid Build Coastguard Worker			contents: emptyElfFile(),
41*333d2b36SAndroid Build Coastguard Worker		},
42*333d2b36SAndroid Build Coastguard Worker		{
43*333d2b36SAndroid Build Coastguard Worker			name:     "short section header",
44*333d2b36SAndroid Build Coastguard Worker			contents: shortSectionHeaderElfFile(),
45*333d2b36SAndroid Build Coastguard Worker		},
46*333d2b36SAndroid Build Coastguard Worker	}
47*333d2b36SAndroid Build Coastguard Worker
48*333d2b36SAndroid Build Coastguard Worker	for _, tt := range tests {
49*333d2b36SAndroid Build Coastguard Worker		t.Run(tt.name, func(t *testing.T) {
50*333d2b36SAndroid Build Coastguard Worker			buf := bytes.NewReader([]byte(tt.contents))
51*333d2b36SAndroid Build Coastguard Worker			_, err := elfIdentifierFromReaderAt(buf, "<>", false)
52*333d2b36SAndroid Build Coastguard Worker			if err == nil {
53*333d2b36SAndroid Build Coastguard Worker				t.Errorf("expected error reading bad elf file without allowMissing")
54*333d2b36SAndroid Build Coastguard Worker			}
55*333d2b36SAndroid Build Coastguard Worker			_, err = elfIdentifierFromReaderAt(buf, "<>", true)
56*333d2b36SAndroid Build Coastguard Worker			if err != nil {
57*333d2b36SAndroid Build Coastguard Worker				t.Errorf("expected no error reading bad elf file with allowMissing, got %q", err.Error())
58*333d2b36SAndroid Build Coastguard Worker			}
59*333d2b36SAndroid Build Coastguard Worker		})
60*333d2b36SAndroid Build Coastguard Worker	}
61*333d2b36SAndroid Build Coastguard Worker}
62*333d2b36SAndroid Build Coastguard Worker
63*333d2b36SAndroid Build Coastguard Workerfunc Test_readNote(t *testing.T) {
64*333d2b36SAndroid Build Coastguard Worker	note := []byte{
65*333d2b36SAndroid Build Coastguard Worker		0x04, 0x00, 0x00, 0x00,
66*333d2b36SAndroid Build Coastguard Worker		0x10, 0x00, 0x00, 0x00,
67*333d2b36SAndroid Build Coastguard Worker		0x03, 0x00, 0x00, 0x00,
68*333d2b36SAndroid Build Coastguard Worker		0x47, 0x4e, 0x55, 0x00,
69*333d2b36SAndroid Build Coastguard Worker		0xca, 0xaf, 0x44, 0xd2, 0x82, 0x78, 0x68, 0xfe, 0xc0, 0x90, 0xa3, 0x43, 0x85, 0x36, 0x6c, 0xc7,
70*333d2b36SAndroid Build Coastguard Worker	}
71*333d2b36SAndroid Build Coastguard Worker
72*333d2b36SAndroid Build Coastguard Worker	descs, err := readNote(bytes.NewBuffer(note), binary.LittleEndian)
73*333d2b36SAndroid Build Coastguard Worker	if err != nil {
74*333d2b36SAndroid Build Coastguard Worker		t.Fatalf("unexpected error in readNote: %s", err)
75*333d2b36SAndroid Build Coastguard Worker	}
76*333d2b36SAndroid Build Coastguard Worker
77*333d2b36SAndroid Build Coastguard Worker	expectedDescs := map[string][]byte{
78*333d2b36SAndroid Build Coastguard Worker		"GNU\x00": []byte{0xca, 0xaf, 0x44, 0xd2, 0x82, 0x78, 0x68, 0xfe, 0xc0, 0x90, 0xa3, 0x43, 0x85, 0x36, 0x6c, 0xc7},
79*333d2b36SAndroid Build Coastguard Worker	}
80*333d2b36SAndroid Build Coastguard Worker
81*333d2b36SAndroid Build Coastguard Worker	if !reflect.DeepEqual(descs, expectedDescs) {
82*333d2b36SAndroid Build Coastguard Worker		t.Errorf("incorrect return, want %#v got %#v", expectedDescs, descs)
83*333d2b36SAndroid Build Coastguard Worker	}
84*333d2b36SAndroid Build Coastguard Worker}
85*333d2b36SAndroid Build Coastguard Worker
86*333d2b36SAndroid Build Coastguard Worker// emptyElfFile returns an elf file header with no program headers or sections.
87*333d2b36SAndroid Build Coastguard Workerfunc emptyElfFile() string {
88*333d2b36SAndroid Build Coastguard Worker	ident := [elf.EI_NIDENT]byte{}
89*333d2b36SAndroid Build Coastguard Worker	identBuf := bytes.NewBuffer(ident[0:0:elf.EI_NIDENT])
90*333d2b36SAndroid Build Coastguard Worker	binary.Write(identBuf, binary.LittleEndian, []byte("\x7fELF"))
91*333d2b36SAndroid Build Coastguard Worker	binary.Write(identBuf, binary.LittleEndian, elf.ELFCLASS64)
92*333d2b36SAndroid Build Coastguard Worker	binary.Write(identBuf, binary.LittleEndian, elf.ELFDATA2LSB)
93*333d2b36SAndroid Build Coastguard Worker	binary.Write(identBuf, binary.LittleEndian, elf.EV_CURRENT)
94*333d2b36SAndroid Build Coastguard Worker	binary.Write(identBuf, binary.LittleEndian, elf.ELFOSABI_LINUX)
95*333d2b36SAndroid Build Coastguard Worker	binary.Write(identBuf, binary.LittleEndian, make([]byte, 8))
96*333d2b36SAndroid Build Coastguard Worker
97*333d2b36SAndroid Build Coastguard Worker	header := elf.Header64{
98*333d2b36SAndroid Build Coastguard Worker		Ident:     ident,
99*333d2b36SAndroid Build Coastguard Worker		Type:      uint16(elf.ET_EXEC),
100*333d2b36SAndroid Build Coastguard Worker		Machine:   uint16(elf.EM_X86_64),
101*333d2b36SAndroid Build Coastguard Worker		Version:   uint32(elf.EV_CURRENT),
102*333d2b36SAndroid Build Coastguard Worker		Entry:     0,
103*333d2b36SAndroid Build Coastguard Worker		Phoff:     uint64(binary.Size(elf.Header64{})),
104*333d2b36SAndroid Build Coastguard Worker		Shoff:     uint64(binary.Size(elf.Header64{})),
105*333d2b36SAndroid Build Coastguard Worker		Flags:     0,
106*333d2b36SAndroid Build Coastguard Worker		Ehsize:    uint16(binary.Size(elf.Header64{})),
107*333d2b36SAndroid Build Coastguard Worker		Phentsize: 0x38,
108*333d2b36SAndroid Build Coastguard Worker		Phnum:     0,
109*333d2b36SAndroid Build Coastguard Worker		Shentsize: 0x40,
110*333d2b36SAndroid Build Coastguard Worker		Shnum:     0,
111*333d2b36SAndroid Build Coastguard Worker		Shstrndx:  0,
112*333d2b36SAndroid Build Coastguard Worker	}
113*333d2b36SAndroid Build Coastguard Worker
114*333d2b36SAndroid Build Coastguard Worker	buf := &bytes.Buffer{}
115*333d2b36SAndroid Build Coastguard Worker	binary.Write(buf, binary.LittleEndian, header)
116*333d2b36SAndroid Build Coastguard Worker	return buf.String()
117*333d2b36SAndroid Build Coastguard Worker}
118*333d2b36SAndroid Build Coastguard Worker
119*333d2b36SAndroid Build Coastguard Worker// shortSectionHeader returns an elf file header with a section header that extends past the end of
120*333d2b36SAndroid Build Coastguard Worker// the file.
121*333d2b36SAndroid Build Coastguard Workerfunc shortSectionHeaderElfFile() string {
122*333d2b36SAndroid Build Coastguard Worker	ident := [elf.EI_NIDENT]byte{}
123*333d2b36SAndroid Build Coastguard Worker	identBuf := bytes.NewBuffer(ident[0:0:elf.EI_NIDENT])
124*333d2b36SAndroid Build Coastguard Worker	binary.Write(identBuf, binary.LittleEndian, []byte("\x7fELF"))
125*333d2b36SAndroid Build Coastguard Worker	binary.Write(identBuf, binary.LittleEndian, elf.ELFCLASS64)
126*333d2b36SAndroid Build Coastguard Worker	binary.Write(identBuf, binary.LittleEndian, elf.ELFDATA2LSB)
127*333d2b36SAndroid Build Coastguard Worker	binary.Write(identBuf, binary.LittleEndian, elf.EV_CURRENT)
128*333d2b36SAndroid Build Coastguard Worker	binary.Write(identBuf, binary.LittleEndian, elf.ELFOSABI_LINUX)
129*333d2b36SAndroid Build Coastguard Worker	binary.Write(identBuf, binary.LittleEndian, make([]byte, 8))
130*333d2b36SAndroid Build Coastguard Worker
131*333d2b36SAndroid Build Coastguard Worker	header := elf.Header64{
132*333d2b36SAndroid Build Coastguard Worker		Ident:     ident,
133*333d2b36SAndroid Build Coastguard Worker		Type:      uint16(elf.ET_EXEC),
134*333d2b36SAndroid Build Coastguard Worker		Machine:   uint16(elf.EM_X86_64),
135*333d2b36SAndroid Build Coastguard Worker		Version:   uint32(elf.EV_CURRENT),
136*333d2b36SAndroid Build Coastguard Worker		Entry:     0,
137*333d2b36SAndroid Build Coastguard Worker		Phoff:     uint64(binary.Size(elf.Header64{})),
138*333d2b36SAndroid Build Coastguard Worker		Shoff:     uint64(binary.Size(elf.Header64{})),
139*333d2b36SAndroid Build Coastguard Worker		Flags:     0,
140*333d2b36SAndroid Build Coastguard Worker		Ehsize:    uint16(binary.Size(elf.Header64{})),
141*333d2b36SAndroid Build Coastguard Worker		Phentsize: 0x38,
142*333d2b36SAndroid Build Coastguard Worker		Phnum:     0,
143*333d2b36SAndroid Build Coastguard Worker		Shentsize: 0x40,
144*333d2b36SAndroid Build Coastguard Worker		Shnum:     1,
145*333d2b36SAndroid Build Coastguard Worker		Shstrndx:  0,
146*333d2b36SAndroid Build Coastguard Worker	}
147*333d2b36SAndroid Build Coastguard Worker
148*333d2b36SAndroid Build Coastguard Worker	buf := &bytes.Buffer{}
149*333d2b36SAndroid Build Coastguard Worker	binary.Write(buf, binary.LittleEndian, header)
150*333d2b36SAndroid Build Coastguard Worker	binary.Write(buf, binary.LittleEndian, []byte{0})
151*333d2b36SAndroid Build Coastguard Worker	return buf.String()
152*333d2b36SAndroid Build Coastguard Worker}
153