/* * Copyright (C) 2023 The Android Open Source Project * * 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 "chre/platform/shared/nanoapp_loader.h" namespace chre { bool NanoappLoader::relocateTable(DynamicHeader *dyn, int tag) { bool success = false; if (dyn == nullptr) { return false; } switch (tag) { case DT_REL: { if (getDynEntry(dyn, tag) == 0) { LOGE("ARM Elf binaries must have DT_REL dynamic entry"); break; } ElfRel *reloc = reinterpret_cast(mBinary + getDynEntry(dyn, DT_REL)); size_t relocSize = getDynEntry(dyn, DT_RELSZ); size_t nRelocs = relocSize / sizeof(ElfRel); LOGV("Relocation %zu entries in DT_REL table", nRelocs); bool resolvedAllSymbols = true; size_t i; for (i = 0; i < nRelocs; ++i) { ElfRel *curr = &reloc[i]; int relocType = ELFW_R_TYPE(curr->r_info); ElfAddr *addr = reinterpret_cast(mMapping + curr->r_offset); switch (relocType) { case R_ARM_RELATIVE: LOGV("Resolving ARM_RELATIVE at offset %lx", static_cast(curr->r_offset)); // TODO(b/155512914): When we move to DRAM allocations, we need to // check if the above address is in a Read-Only section of memory, // and give it temporary write permission if that is the case. *addr += reinterpret_cast(mMapping); break; case R_ARM_ABS32: { LOGV("Resolving ARM_ABS32 at offset %lx", static_cast(curr->r_offset)); size_t posInSymbolTable = ELFW_R_SYM(curr->r_info); auto *dynamicSymbolTable = reinterpret_cast(mDynamicSymbolTablePtr); ElfSym *sym = &dynamicSymbolTable[posInSymbolTable]; *addr = reinterpret_cast(mMapping + sym->st_value); break; } case R_ARM_GLOB_DAT: { LOGV("Resolving type ARM_GLOB_DAT at offset %lx", static_cast(curr->r_offset)); size_t posInSymbolTable = ELFW_R_SYM(curr->r_info); void *resolved = resolveData(posInSymbolTable); if (resolved == nullptr) { LOGV("Failed to resolve global symbol(%zu) at offset 0x%lx", i, static_cast(curr->r_offset)); resolvedAllSymbols = false; } // TODO(b/155512914): When we move to DRAM allocations, we need to // check if the above address is in a Read-Only section of memory, // and give it temporary write permission if that is the case. *addr = reinterpret_cast(resolved); break; } case R_ARM_COPY: LOGE("R_ARM_COPY is an invalid relocation for shared libraries"); break; default: LOGE("Invalid relocation type %u", relocType); break; } } if (!resolvedAllSymbols) { LOGE("Unable to resolve all symbols in the binary"); } else { success = true; } break; } case DT_RELA: if (getDynEntry(dyn, tag) != 0) { LOGE("ARM Elf binaries with a DT_RELA dynamic entry are unsupported"); } else { // Not required for ARM success = true; } break; default: LOGE("Unsupported table tag %d", tag); } return success; } bool NanoappLoader::resolveGot() { ElfAddr *addr; ElfRel *reloc = reinterpret_cast( mMapping + getDynEntry(getDynamicHeader(), DT_JMPREL)); size_t relocSize = getDynEntry(getDynamicHeader(), DT_PLTRELSZ); size_t nRelocs = relocSize / sizeof(ElfRel); LOGV("Resolving GOT with %zu relocations", nRelocs); bool success = true; for (size_t i = 0; i < nRelocs; ++i) { ElfRel *curr = &reloc[i]; int relocType = ELFW_R_TYPE(curr->r_info); switch (relocType) { case R_ARM_JUMP_SLOT: { LOGV("Resolving ARM_JUMP_SLOT at offset %lx", static_cast(curr->r_offset)); addr = reinterpret_cast(mMapping + curr->r_offset); size_t posInSymbolTable = ELFW_R_SYM(curr->r_info); void *resolved = resolveData(posInSymbolTable); if (resolved == nullptr) { LOGE("Failed to resolve symbol(%zu) at offset 0x%x", i, curr->r_offset); success = false; } *addr = reinterpret_cast(resolved); break; } default: LOGE("Unsupported relocation type: %u for symbol %s", relocType, getDataName(getDynamicSymbol(ELFW_R_SYM(curr->r_info)))); success = false; } } return success; } } // namespace chre