1 /*
2 * Copyright (C) 2023 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 "chre/platform/shared/nanoapp_loader.h"
18
19 namespace chre {
20
relocateTable(DynamicHeader * dyn,int tag)21 bool NanoappLoader::relocateTable(DynamicHeader *dyn, int tag) {
22 bool success = false;
23 if (dyn == nullptr) {
24 return false;
25 }
26
27 switch (tag) {
28 case DT_RELA: {
29 if (getDynEntry(dyn, tag) == 0) {
30 LOGE("RISC-V Elf binaries must have DT_RELA dynamic entry");
31 break;
32 }
33
34 // The value of the RELA entry in dynamic table is the sh_addr field
35 // of ".rela.dyn" section header. We actually need to use the sh_offset
36 // which is usually the same, but on occasions can be different.
37 SectionHeader *dynamicRelaTablePtr = getSectionHeader(".rela.dyn");
38 CHRE_ASSERT(dynamicRelaTablePtr != nullptr);
39 ElfRela *reloc =
40 reinterpret_cast<ElfRela *>(mBinary + dynamicRelaTablePtr->sh_offset);
41 size_t relocSize = dynamicRelaTablePtr->sh_size;
42 size_t nRelocs = relocSize / sizeof(ElfRela);
43 LOGV("Relocation %zu entries in DT_RELA table", nRelocs);
44
45 for (size_t i = 0; i < nRelocs; ++i) {
46 ElfRela *curr = &reloc[i];
47 int relocType = ELFW_R_TYPE(curr->r_info);
48 ElfAddr *addr = reinterpret_cast<ElfAddr *>(mMapping + curr->r_offset);
49
50 switch (relocType) {
51 case R_RISCV_RELATIVE:
52 LOGV("Resolving RISCV_RELATIVE at offset %lx",
53 static_cast<long unsigned int>(curr->r_offset));
54 // TODO(b/155512914): When we move to DRAM allocations, we need to
55 // check if the above address is in a Read-Only section of memory,
56 // and give it temporary write permission if that is the case.
57 *addr = reinterpret_cast<uintptr_t>(mMapping + curr->r_addend);
58 break;
59
60 case R_RISCV_32: {
61 LOGV("Resolving RISCV_32 at offset %lx",
62 static_cast<long unsigned int>(curr->r_offset));
63 size_t posInSymbolTable = ELFW_R_SYM(curr->r_info);
64 auto *dynamicSymbolTable =
65 reinterpret_cast<ElfSym *>(mDynamicSymbolTablePtr);
66 ElfSym *sym = &dynamicSymbolTable[posInSymbolTable];
67 *addr = reinterpret_cast<uintptr_t>(mMapping + sym->st_value);
68 break;
69 }
70
71 default:
72 LOGE("Unsupported relocation type %u", relocType);
73 break;
74 }
75 }
76 success = true;
77 break;
78 }
79 case DT_REL:
80 // Not required for RISC-V
81 success = true;
82 break;
83 default:
84 LOGE("Unsupported table tag %d", tag);
85 }
86
87 return success;
88 }
89
resolveGot()90 bool NanoappLoader::resolveGot() {
91 ElfAddr *addr;
92 ElfRela *reloc = reinterpret_cast<ElfRela *>(
93 mMapping + getDynEntry(getDynamicHeader(), DT_JMPREL));
94 size_t relocSize = getDynEntry(getDynamicHeader(), DT_PLTRELSZ);
95 size_t nRelocs = relocSize / sizeof(ElfRela);
96 LOGV("Resolving GOT with %zu relocations", nRelocs);
97
98 bool success = true;
99
100 for (size_t i = 0; i < nRelocs; ++i) {
101 ElfRela *curr = &reloc[i];
102 int relocType = ELFW_R_TYPE(curr->r_info);
103
104 switch (relocType) {
105 case R_RISCV_JUMP_SLOT: {
106 LOGV("Resolving RISCV_JUMP_SLOT at offset %lx, %d",
107 static_cast<long unsigned int>(curr->r_offset), curr->r_addend);
108 addr = reinterpret_cast<ElfAddr *>(mMapping + curr->r_offset);
109 size_t posInSymbolTable = ELFW_R_SYM(curr->r_info);
110 void *resolved = resolveData(posInSymbolTable);
111 if (resolved == nullptr) {
112 LOGE("Failed to resolve symbol(%zu) at offset 0x%x", i,
113 curr->r_offset);
114 success = false;
115 }
116 *addr = reinterpret_cast<ElfAddr>(resolved) + curr->r_addend;
117 break;
118 }
119
120 default:
121 LOGE("Unsupported relocation type: %u for symbol %s", relocType,
122 getDataName(getDynamicSymbol(ELFW_R_SYM(curr->r_info))));
123 success = false;
124 }
125 }
126 return success;
127 }
128
129 } // namespace chre
130