xref: /aosp_15_r20/external/pigweed/pw_elf/reader_test.cc (revision 61c4878ac05f98d0ceed94b57d316916de578985)
1 // Copyright 2024 The Pigweed Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License"); you may not
4 // use this file except in compliance with the License. You may obtain a copy of
5 // the License at
6 //
7 //     https://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, WITHOUT
11 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 // License for the specific language governing permissions and limitations under
13 // the License.
14 
15 #include "pw_elf/reader.h"
16 
17 #include "pw_bytes/array.h"
18 #include "pw_bytes/endian.h"
19 #include "pw_bytes/suffix.h"
20 #include "pw_stream/memory_stream.h"
21 #include "pw_stream/std_file_stream.h"
22 #include "pw_unit_test/framework.h"
23 
24 namespace pw::elf {
25 namespace {
26 
27 constexpr Status kEndOfFileStatus = Status::OutOfRange();
28 
TestInitialize(ConstByteSpan data)29 Status TestInitialize(ConstByteSpan data) {
30   stream::MemoryReader stream(data);
31   return ElfReader::FromStream(stream).status();
32 }
33 
TEST(Reader,HandlesEmptyStream)34 TEST(Reader, HandlesEmptyStream) {
35   constexpr auto kData = bytes::Array<>();
36   EXPECT_EQ(TestInitialize(kData), kEndOfFileStatus);
37 }
38 
TEST(Reader,HandlesInvalidMagic)39 TEST(Reader, HandlesInvalidMagic) {
40   constexpr std::array<std::byte, EI_NIDENT> kData = {
41       std::byte{0x7F},
42       std::byte{'B'},
43       std::byte{'A'},
44       std::byte{'D'},
45   };
46   EXPECT_EQ(TestInitialize(kData), Status::DataLoss());
47 }
48 
TEST(Reader,HandlesTruncatedAfterMagic)49 TEST(Reader, HandlesTruncatedAfterMagic) {
50   constexpr auto kData = bytes::Array<0x7F, 'E', 'L', 'F'>();
51   EXPECT_EQ(TestInitialize(kData), kEndOfFileStatus);
52 }
53 
TEST(Reader,HandlesInvalidClass)54 TEST(Reader, HandlesInvalidClass) {
55   constexpr std::array<std::byte, EI_NIDENT> kData = {
56       std::byte{0x7F},
57       std::byte{'E'},
58       std::byte{'L'},
59       std::byte{'F'},
60       std::byte{0x66},  // EI_CLASS
61       std::byte{pw::endian::native == pw::endian::little
62                     ? ELFDATA2LSB
63                     : ELFDATA2MSB},  // EI_DATA
64   };
65   EXPECT_EQ(TestInitialize(kData), Status::DataLoss());
66 }
67 
TEST(Reader,HandlesUnsupportedEndian)68 TEST(Reader, HandlesUnsupportedEndian) {
69   constexpr std::array<std::byte, EI_NIDENT> kData = {
70       std::byte{0x7F},
71       std::byte{'E'},
72       std::byte{'L'},
73       std::byte{'F'},
74       std::byte{0x66},  // EI_CLASS
75       std::byte{pw::endian::native == pw::endian::little
76                     ? ELFDATA2MSB
77                     : ELFDATA2LSB},  // EI_DATA (opposite)
78   };
79   EXPECT_EQ(TestInitialize(kData), Status::Unimplemented());
80 }
81 
TEST(Reader,SeekToSectionWorksOnRealFile)82 TEST(Reader, SeekToSectionWorksOnRealFile) {
83   pw::stream::StdFileReader stream(TEST_ELF_FILE_PATH);
84   PW_TEST_ASSERT_OK_AND_ASSIGN(auto reader,
85                                pw::elf::ElfReader::FromStream(stream));
86 
87   auto section_size = reader.SeekToSection(".test_section_1");
88   PW_TEST_ASSERT_OK(section_size);
89 
90   std::vector<std::byte> section_data;
91   section_data.resize(section_size.size());
92   PW_TEST_ASSERT_OK(stream.ReadExact(section_data));
93 
94   constexpr auto kExpectedData = bytes::String("You cannot pass\0");
95   EXPECT_EQ(section_data.size(), kExpectedData.size());
96   EXPECT_TRUE(std::equal(
97       section_data.begin(), section_data.end(), kExpectedData.begin()));
98 }
99 
TEST(Reader,ReadSectionWorksOnRealFile)100 TEST(Reader, ReadSectionWorksOnRealFile) {
101   pw::stream::StdFileReader stream(TEST_ELF_FILE_PATH);
102   PW_TEST_ASSERT_OK_AND_ASSIGN(auto reader,
103                                pw::elf::ElfReader::FromStream(stream));
104 
105   PW_TEST_ASSERT_OK_AND_ASSIGN(auto section_data,
106                                reader.ReadSection(".test_section_2"));
107 
108   constexpr auto kExpectedData = bytes::Array<0xEF, 0xBE, 0xED, 0xFE>();
109   EXPECT_EQ(section_data.size(), kExpectedData.size());
110   EXPECT_TRUE(std::equal(
111       section_data.begin(), section_data.end(), kExpectedData.begin()));
112 }
113 
114 }  // namespace
115 }  // namespace pw::elf
116