• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2016 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <elf.h>
18 
19 #include <gtest/gtest.h>
20 
21 #include "Elf.h"
22 
23 #include "MemoryFake.h"
24 
25 #if !defined(PT_ARM_EXIDX)
26 #define PT_ARM_EXIDX 0x70000001
27 #endif
28 
29 #if !defined(EM_AARCH64)
30 #define EM_AARCH64 183
31 #endif
32 
33 class ElfTest : public ::testing::Test {
34  protected:
SetUp()35   void SetUp() override {
36     memory_ = new MemoryFake;
37   }
38 
39   template <typename Ehdr>
InitEhdr(Ehdr * ehdr)40   void InitEhdr(Ehdr* ehdr) {
41     memset(ehdr, 0, sizeof(Ehdr));
42     memcpy(&ehdr->e_ident[0], ELFMAG, SELFMAG);
43     ehdr->e_ident[EI_DATA] = ELFDATA2LSB;
44     ehdr->e_ident[EI_VERSION] = EV_CURRENT;
45     ehdr->e_ident[EI_OSABI] = ELFOSABI_SYSV;
46   }
47 
InitElf32(uint32_t type)48   void InitElf32(uint32_t type) {
49     Elf32_Ehdr ehdr;
50 
51     InitEhdr<Elf32_Ehdr>(&ehdr);
52     ehdr.e_ident[EI_CLASS] = ELFCLASS32;
53 
54     ehdr.e_type = ET_DYN;
55     ehdr.e_machine = type;
56     ehdr.e_version = EV_CURRENT;
57     ehdr.e_entry = 0;
58     ehdr.e_phoff = 0x100;
59     ehdr.e_shoff = 0;
60     ehdr.e_flags = 0;
61     ehdr.e_ehsize = sizeof(ehdr);
62     ehdr.e_phentsize = sizeof(Elf32_Phdr);
63     ehdr.e_phnum = 1;
64     ehdr.e_shentsize = sizeof(Elf32_Shdr);
65     ehdr.e_shnum = 0;
66     ehdr.e_shstrndx = 0;
67     if (type == EM_ARM) {
68       ehdr.e_flags = 0x5000200;
69       ehdr.e_phnum = 2;
70     }
71     memory_->SetMemory(0, &ehdr, sizeof(ehdr));
72 
73     Elf32_Phdr phdr;
74     memset(&phdr, 0, sizeof(phdr));
75     phdr.p_type = PT_LOAD;
76     phdr.p_offset = 0;
77     phdr.p_vaddr = 0;
78     phdr.p_paddr = 0;
79     phdr.p_filesz = 0x10000;
80     phdr.p_memsz = 0x10000;
81     phdr.p_flags = PF_R | PF_X;
82     phdr.p_align = 0x1000;
83     memory_->SetMemory(0x100, &phdr, sizeof(phdr));
84 
85     if (type == EM_ARM) {
86       memset(&phdr, 0, sizeof(phdr));
87       phdr.p_type = PT_ARM_EXIDX;
88       phdr.p_offset = 0x30000;
89       phdr.p_vaddr = 0x30000;
90       phdr.p_paddr = 0x30000;
91       phdr.p_filesz = 16;
92       phdr.p_memsz = 16;
93       phdr.p_flags = PF_R;
94       phdr.p_align = 0x4;
95       memory_->SetMemory(0x100 + sizeof(phdr), &phdr, sizeof(phdr));
96     }
97   }
98 
InitElf64(uint32_t type)99   void InitElf64(uint32_t type) {
100     Elf64_Ehdr ehdr;
101 
102     InitEhdr<Elf64_Ehdr>(&ehdr);
103     ehdr.e_ident[EI_CLASS] = ELFCLASS64;
104 
105     ehdr.e_type = ET_DYN;
106     ehdr.e_machine = type;
107     ehdr.e_version = EV_CURRENT;
108     ehdr.e_entry = 0;
109     ehdr.e_phoff = 0x100;
110     ehdr.e_shoff = 0;
111     ehdr.e_flags = 0x5000200;
112     ehdr.e_ehsize = sizeof(ehdr);
113     ehdr.e_phentsize = sizeof(Elf64_Phdr);
114     ehdr.e_phnum = 1;
115     ehdr.e_shentsize = sizeof(Elf64_Shdr);
116     ehdr.e_shnum = 0;
117     ehdr.e_shstrndx = 0;
118     memory_->SetMemory(0, &ehdr, sizeof(ehdr));
119 
120     Elf64_Phdr phdr;
121     memset(&phdr, 0, sizeof(phdr));
122     phdr.p_type = PT_LOAD;
123     phdr.p_offset = 0;
124     phdr.p_vaddr = 0;
125     phdr.p_paddr = 0;
126     phdr.p_filesz = 0x10000;
127     phdr.p_memsz = 0x10000;
128     phdr.p_flags = PF_R | PF_X;
129     phdr.p_align = 0x1000;
130     memory_->SetMemory(0x100, &phdr, sizeof(phdr));
131   }
132 
133   MemoryFake* memory_;
134 };
135 
TEST_F(ElfTest,invalid_memory)136 TEST_F(ElfTest, invalid_memory) {
137   Elf elf(memory_);
138 
139   ASSERT_FALSE(elf.Init());
140   ASSERT_FALSE(elf.valid());
141 }
142 
TEST_F(ElfTest,elf_invalid)143 TEST_F(ElfTest, elf_invalid) {
144   Elf elf(memory_);
145 
146   InitElf32(EM_386);
147 
148   // Corrupt the ELF signature.
149   memory_->SetData32(0, 0x7f000000);
150 
151   ASSERT_FALSE(elf.Init());
152   ASSERT_FALSE(elf.valid());
153   ASSERT_TRUE(elf.interface() == nullptr);
154 
155   std::string name;
156   ASSERT_FALSE(elf.GetSoname(&name));
157 
158   uint64_t func_offset;
159   ASSERT_FALSE(elf.GetFunctionName(0, &name, &func_offset));
160 
161   ASSERT_FALSE(elf.Step(0, nullptr, nullptr));
162 }
163 
TEST_F(ElfTest,elf_arm)164 TEST_F(ElfTest, elf_arm) {
165   Elf elf(memory_);
166 
167   InitElf32(EM_ARM);
168 
169   ASSERT_TRUE(elf.Init());
170   ASSERT_TRUE(elf.valid());
171   ASSERT_EQ(static_cast<uint32_t>(EM_ARM), elf.machine_type());
172   ASSERT_EQ(ELFCLASS32, elf.class_type());
173   ASSERT_TRUE(elf.interface() != nullptr);
174 }
175 
TEST_F(ElfTest,elf_x86)176 TEST_F(ElfTest, elf_x86) {
177   Elf elf(memory_);
178 
179   InitElf32(EM_386);
180 
181   ASSERT_TRUE(elf.Init());
182   ASSERT_TRUE(elf.valid());
183   ASSERT_EQ(static_cast<uint32_t>(EM_386), elf.machine_type());
184   ASSERT_EQ(ELFCLASS32, elf.class_type());
185   ASSERT_TRUE(elf.interface() != nullptr);
186 }
187 
TEST_F(ElfTest,elf_arm64)188 TEST_F(ElfTest, elf_arm64) {
189   Elf elf(memory_);
190 
191   InitElf64(EM_AARCH64);
192 
193   ASSERT_TRUE(elf.Init());
194   ASSERT_TRUE(elf.valid());
195   ASSERT_EQ(static_cast<uint32_t>(EM_AARCH64), elf.machine_type());
196   ASSERT_EQ(ELFCLASS64, elf.class_type());
197   ASSERT_TRUE(elf.interface() != nullptr);
198 }
199 
TEST_F(ElfTest,elf_x86_64)200 TEST_F(ElfTest, elf_x86_64) {
201   Elf elf(memory_);
202 
203   InitElf64(EM_X86_64);
204 
205   ASSERT_TRUE(elf.Init());
206   ASSERT_TRUE(elf.valid());
207   ASSERT_EQ(static_cast<uint32_t>(EM_X86_64), elf.machine_type());
208   ASSERT_EQ(ELFCLASS64, elf.class_type());
209   ASSERT_TRUE(elf.interface() != nullptr);
210 }
211