* Copyright 2012-2018, Haiku, Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Ithamar R. Adema <ithamar@upgrade-android.com>
*/
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include "runtime_loader_private.h"
#include <runtime_loader.h>
static status_t
relocate_rela(image_t* rootImage, image_t* image, Elf64_Rela* rel,
size_t relLength, SymbolLookupCache* cache)
{
for (size_t i = 0; i < relLength / sizeof(Elf64_Rela); i++) {
int type = ELF64_R_TYPE(rel[i].r_info);
int symIndex = ELF64_R_SYM(rel[i].r_info);
Elf64_Addr symAddr = 0;
image_t* symbolImage = NULL;
if (symIndex != 0) {
Elf64_Sym* sym = SYMBOL(image, symIndex);
status_t status = resolve_symbol(rootImage, image, sym, cache,
&symAddr, &symbolImage);
if (status != B_OK) {
TRACE(("resolve symbol \"%s\" returned: %" B_PRId32 "\n",
SYMNAME(image, sym), status));
printf("resolve symbol \"%s\" returned: %" B_PRId32 "\n",
SYMNAME(image, sym), status);
return status;
}
}
Elf64_Addr relocAddr = image->regions[0].delta + rel[i].r_offset;
Elf64_Addr relocValue;
switch (type) {
case R_RISCV_NONE:
continue;
case R_RISCV_64:
case R_RISCV_JUMP_SLOT:
relocValue = symAddr + rel[i].r_addend;
break;
case R_RISCV_RELATIVE:
relocValue = image->regions[0].delta + rel[i].r_addend;
break;
case R_RISCV_TLS_DTPMOD64:
relocValue = symbolImage == NULL
? image->dso_tls_id : symbolImage->dso_tls_id;
break;
case R_RISCV_TLS_DTPREL64:
relocValue = symAddr;
break;
default:
TRACE(("unhandled relocation type %d\n", type));
return B_BAD_DATA;
}
*(Elf64_Addr *)relocAddr = relocValue;
}
return B_OK;
}
status_t
arch_relocate_image(image_t* rootImage, image_t* image,
SymbolLookupCache* cache)
{
status_t status;
if (image->rela) {
status = relocate_rela(rootImage, image, image->rela, image->rela_len,
cache);
if (status != B_OK)
return status;
}
if (image->pltrel) {
status = relocate_rela(rootImage, image, (Elf64_Rela*)image->pltrel,
image->pltrel_len, cache);
if (status != B_OK)
return status;
}
return B_OK;
}