2 * Copyright (c) 2021 Samsung Electronics Co., Ltd All Rights Reserved
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
24 #include <pal_endian.h>
27 #include <inc/corhdr.h>
28 #include <inc/readytorun.h>
31 #include <r2r_checker.h>
33 static inline UINT AlignUp(UINT value, UINT alignment)
35 return (value + alignment - 1) & ~(alignment - 1);
38 static inline UINT64 AlignUp(UINT64 value, UINT alignment)
40 return (value + alignment - 1)& ~(UINT64)(alignment - 1);
43 static IMAGE_NT_HEADERS* getNTHeaders(void* pAddr)
45 IMAGE_DOS_HEADER* pDOS = (IMAGE_DOS_HEADER*)pAddr;
46 if (pDOS->e_magic != VAL16(IMAGE_DOS_SIGNATURE)) return NULL;
48 return (IMAGE_NT_HEADERS*)((ULONG_PTR)pAddr + VAL32(pDOS->e_lfanew));
51 static IMAGE_DATA_DIRECTORY* getCorDirectoryEntry(IMAGE_NT_HEADERS* pNTHeaders)
53 IMAGE_DATA_DIRECTORY* pDir = NULL;
54 if (pNTHeaders->OptionalHeader.Magic == VAL16(IMAGE_NT_OPTIONAL_HDR32_MAGIC)) {
55 pDir = (IMAGE_DATA_DIRECTORY*)((ULONG_PTR)(pNTHeaders)
56 + offsetof(IMAGE_NT_HEADERS32, OptionalHeader.DataDirectory)
57 + IMAGE_DIRECTORY_ENTRY_COMHEADER * sizeof(IMAGE_DATA_DIRECTORY));
58 } else if (pNTHeaders->OptionalHeader.Magic == VAL16(IMAGE_NT_OPTIONAL_HDR64_MAGIC)) {
59 pDir = (IMAGE_DATA_DIRECTORY*)((ULONG_PTR)(pNTHeaders)
60 + offsetof(IMAGE_NT_HEADERS64, OptionalHeader.DataDirectory)
61 + IMAGE_DIRECTORY_ENTRY_COMHEADER * sizeof(IMAGE_DATA_DIRECTORY));
63 _SERR("Invalid Optional Header Magic Number: 0x%x", VAL16(pNTHeaders->OptionalHeader.Magic));
69 static IMAGE_SECTION_HEADER* findFirstSection(IMAGE_NT_HEADERS* pNTHeaders)
71 return (IMAGE_SECTION_HEADER*)(
72 (ULONG_PTR)(pNTHeaders) +
73 offsetof(IMAGE_NT_HEADERS, OptionalHeader) +
74 VAL16(pNTHeaders->FileHeader.SizeOfOptionalHeader));
77 static IMAGE_SECTION_HEADER* getSection(IMAGE_NT_HEADERS* pNTHeaders, UINT rva) {
78 IMAGE_SECTION_HEADER* section = (IMAGE_SECTION_HEADER*)(findFirstSection(pNTHeaders));
79 IMAGE_SECTION_HEADER* sectionEnd = section + VAL16(pNTHeaders->FileHeader.NumberOfSections);
80 while (section < sectionEnd) {
81 if (rva < (VAL32(section->VirtualAddress)
82 + AlignUp((UINT)VAL32(section->Misc.VirtualSize), (UINT)VAL32(pNTHeaders->OptionalHeader.SectionAlignment)))) {
83 if (rva < VAL32(section->VirtualAddress)) {
95 static ULONG_PTR getDirectoryData(void* pBaseAddr, IMAGE_NT_HEADERS* pNTHeaders, IMAGE_DATA_DIRECTORY* pDir) {
96 UINT rva = pDir->VirtualAddress;
101 IMAGE_SECTION_HEADER* section = getSection(pNTHeaders, rva);
106 return (ULONG_PTR)pBaseAddr + rva - VAL32(section->VirtualAddress) + VAL32(section->PointerToRawData);
109 static bool hasValidR2RHeader(void* pAddr)
111 IMAGE_NT_HEADERS* pNTHeaders = getNTHeaders(pAddr);
113 _SERR("Invalid NT Header");
117 IMAGE_DATA_DIRECTORY* pCorDir = getCorDirectoryEntry(pNTHeaders);
119 _SERR("Invalid Cor Data Directory");
123 IMAGE_COR20_HEADER* pCor = (IMAGE_COR20_HEADER*)getDirectoryData(pAddr, pNTHeaders, pCorDir);
125 _SERR("Invalid Cor Header");
129 IMAGE_DATA_DIRECTORY* pR2RDir = &pCor->ManagedNativeHeader;
130 if (VAL32(pR2RDir->Size) >= sizeof(READYTORUN_HEADER)) {
131 READYTORUN_HEADER* pR2RHeader = (READYTORUN_HEADER*)getDirectoryData(pAddr, pNTHeaders, pR2RDir);
136 if (pR2RHeader->Signature != VAL16(READYTORUN_SIGNATURE)) {
144 bool isR2RImage(std::string fileName)
148 if ((fd = open(fileName.c_str(), O_RDONLY)) == -1) {
149 _SERR("File Not Found: %s", fileName.c_str());
153 if (fstat(fd, &sb) == -1) {
158 void* pAddr = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
159 if (pAddr == MAP_FAILED) {
160 _SERR("Fail to Map File: %s", fileName.c_str());
165 bool ret = hasValidR2RHeader(pAddr);
167 munmap(pAddr, sb.st_size);
172 unsigned int getSizeOfImage(std::string fileName)
176 if ((fd = open(fileName.c_str(), O_RDONLY)) == -1) {
177 _SERR("File Not Found: %s", fileName.c_str());
181 if (fstat(fd, &sb) == -1) {
186 void* pAddr = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
187 if (pAddr == MAP_FAILED) {
188 _SERR("Fail to Map File: %s", fileName.c_str());
193 IMAGE_NT_HEADERS* pNTHeaders = getNTHeaders(pAddr);
195 _SERR("Invalid NT Header");
196 munmap(pAddr, sb.st_size);
201 // typedef unsigned int ULONG;
202 unsigned int ret = pNTHeaders->OptionalHeader.SizeOfImage;
204 munmap(pAddr, sb.st_size);