blob: a22077090397b876f9095beed732d13dcc8f564b [file] [log] [blame]
Colin Cross36f55aa2022-03-21 18:46:41 -07001// 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
Peter Collingbourne941ff1d2024-03-14 21:17:21 -070015package elf
Colin Cross36f55aa2022-03-21 18:46:41 -070016
17import (
18 "bytes"
Colin Cross6285c652022-04-05 18:06:15 -070019 "debug/elf"
Colin Cross36f55aa2022-03-21 18:46:41 -070020 "encoding/binary"
21 "reflect"
22 "testing"
23)
24
Colin Cross6285c652022-04-05 18:06:15 -070025func 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 },
Colin Cross338df532022-04-11 18:42:34 -070042 {
43 name: "short section header",
44 contents: shortSectionHeaderElfFile(),
45 },
Colin Cross6285c652022-04-05 18:06:15 -070046 }
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
Colin Cross36f55aa2022-03-21 18:46:41 -070063func 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}
Colin Cross6285c652022-04-05 18:06:15 -070085
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}
Colin Cross338df532022-04-11 18:42:34 -0700118
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}