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