blob: b2b94d27b6fcc528933e9b048e039cc888108ae8 [file] [log] [blame]
// Copyright 2019 The Cobalt Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "starboard/elf_loader/elf_header.h"
#include "starboard/common/scoped_ptr.h"
#include "starboard/elf_loader/file.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#if SB_API_VERSION >= 12 && \
(SB_API_VERSION >= SB_MMAP_REQUIRED_VERSION || SB_HAS(MMAP)) && \
SB_CAN(MAP_EXECUTABLE_MEMORY)
namespace starboard {
namespace elf_loader {
namespace {
class DummyFile : public File {
public:
DummyFile(const char* buffer, int size) : buffer_(buffer), size_(size) {}
bool Open(const char* name) { return true; }
bool ReadFromOffset(int64_t offset, char* buffer, int size) {
SB_LOG(INFO) << "ReadFromOffset";
if (offset != 0) {
SB_LOG(ERROR) << "ReadFromOffset: Invalid offset " << offset;
return false;
}
if (size < size_) {
SB_LOG(ERROR) << "ReadFromOffset: Invalid size " << size;
return false;
}
SbMemoryCopy(buffer, buffer_, size);
return true;
}
void Close() {}
private:
const char* buffer_;
int size_;
};
class ElfHeaderTest : public ::testing::Test {
protected:
ElfHeaderTest() {
elf_header_.reset(new ElfHeader());
SbMemorySet(reinterpret_cast<char*>(&ehdr_data_), 0, sizeof(ehdr_data_));
ehdr_data_.e_machine = ELF_MACHINE;
ehdr_data_.e_ident[0] = 0x7F;
ehdr_data_.e_ident[1] = 'E';
ehdr_data_.e_ident[2] = 'L';
ehdr_data_.e_ident[3] = 'F';
ehdr_data_.e_ident[EI_CLASS] = ELF_CLASS_VALUE;
ehdr_data_.e_ident[EI_DATA] = ELFDATA2LSB;
ehdr_data_.e_type = ET_DYN;
ehdr_data_.e_version = EV_CURRENT;
ehdr_data_.e_machine = ELF_MACHINE;
dummy_file_.reset(new DummyFile(reinterpret_cast<const char*>(&ehdr_data_),
sizeof(ehdr_data_)));
}
~ElfHeaderTest() {}
scoped_ptr<ElfHeader> elf_header_;
Ehdr ehdr_data_;
scoped_ptr<DummyFile> dummy_file_;
};
TEST_F(ElfHeaderTest, Initialize) {
EXPECT_TRUE(elf_header_->LoadElfHeader(dummy_file_.get()));
}
TEST_F(ElfHeaderTest, NegativeBadImage) {
ehdr_data_.e_ident[1] = 'F';
dummy_file_.reset(new DummyFile(reinterpret_cast<const char*>(&ehdr_data_),
sizeof(ehdr_data_)));
EXPECT_FALSE(elf_header_->LoadElfHeader(dummy_file_.get()));
}
TEST_F(ElfHeaderTest, NegativeBadClass) {
ehdr_data_.e_ident[EI_CLASS] = 0;
dummy_file_.reset(new DummyFile(reinterpret_cast<const char*>(&ehdr_data_),
sizeof(ehdr_data_)));
EXPECT_FALSE(elf_header_->LoadElfHeader(dummy_file_.get()));
}
TEST_F(ElfHeaderTest, NegativeWrongGulliverLilliput) {
ehdr_data_.e_type = 2;
dummy_file_.reset(new DummyFile(reinterpret_cast<const char*>(&ehdr_data_),
sizeof(ehdr_data_)));
EXPECT_FALSE(elf_header_->LoadElfHeader(dummy_file_.get()));
}
TEST_F(ElfHeaderTest, NegativeBadType) {
ehdr_data_.e_type = 2;
dummy_file_.reset(new DummyFile(reinterpret_cast<const char*>(&ehdr_data_),
sizeof(ehdr_data_)));
EXPECT_FALSE(elf_header_->LoadElfHeader(dummy_file_.get()));
}
TEST_F(ElfHeaderTest, NegativeBadVersion) {
ehdr_data_.e_version = 2;
dummy_file_.reset(new DummyFile(reinterpret_cast<const char*>(&ehdr_data_),
sizeof(ehdr_data_)));
EXPECT_FALSE(elf_header_->LoadElfHeader(dummy_file_.get()));
}
TEST_F(ElfHeaderTest, NegativeBadMachine) {
ehdr_data_.e_machine = 0;
dummy_file_.reset(new DummyFile(reinterpret_cast<const char*>(&ehdr_data_),
sizeof(ehdr_data_)));
EXPECT_FALSE(elf_header_->LoadElfHeader(dummy_file_.get()));
}
} // namespace
} // namespace elf_loader
} // namespace starboard
#endif // SB_API_VERSION >= 12 && (SB_API_VERSION >= SB_MMAP_REQUIRED_VERSION
// || SB_HAS(MMAP)) && SB_CAN(MAP_EXECUTABLE_MEMORY)