1da0c48c4Sopenharmony_ci/* Common code for ebl reloc functions. 2da0c48c4Sopenharmony_ci Copyright (C) 2005, 2006 Red Hat, Inc. 3da0c48c4Sopenharmony_ci This file is part of elfutils. 4da0c48c4Sopenharmony_ci 5da0c48c4Sopenharmony_ci This file is free software; you can redistribute it and/or modify 6da0c48c4Sopenharmony_ci it under the terms of either 7da0c48c4Sopenharmony_ci 8da0c48c4Sopenharmony_ci * the GNU Lesser General Public License as published by the Free 9da0c48c4Sopenharmony_ci Software Foundation; either version 3 of the License, or (at 10da0c48c4Sopenharmony_ci your option) any later version 11da0c48c4Sopenharmony_ci 12da0c48c4Sopenharmony_ci or 13da0c48c4Sopenharmony_ci 14da0c48c4Sopenharmony_ci * the GNU General Public License as published by the Free 15da0c48c4Sopenharmony_ci Software Foundation; either version 2 of the License, or (at 16da0c48c4Sopenharmony_ci your option) any later version 17da0c48c4Sopenharmony_ci 18da0c48c4Sopenharmony_ci or both in parallel, as here. 19da0c48c4Sopenharmony_ci 20da0c48c4Sopenharmony_ci elfutils is distributed in the hope that it will be useful, but 21da0c48c4Sopenharmony_ci WITHOUT ANY WARRANTY; without even the implied warranty of 22da0c48c4Sopenharmony_ci MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 23da0c48c4Sopenharmony_ci General Public License for more details. 24da0c48c4Sopenharmony_ci 25da0c48c4Sopenharmony_ci You should have received copies of the GNU General Public License and 26da0c48c4Sopenharmony_ci the GNU Lesser General Public License along with this program. If 27da0c48c4Sopenharmony_ci not, see <http://www.gnu.org/licenses/>. */ 28da0c48c4Sopenharmony_ci 29da0c48c4Sopenharmony_ci#include "libebl_CPU.h" 30da0c48c4Sopenharmony_ci#include <assert.h> 31da0c48c4Sopenharmony_ci 32da0c48c4Sopenharmony_ci#define R_TYPE(name) PASTE (RELOC_PREFIX, name) 33da0c48c4Sopenharmony_ci#define PASTE(a, b) PASTE_1 (a, b) 34da0c48c4Sopenharmony_ci#define PASTE_1(a, b) a##b 35da0c48c4Sopenharmony_ci#define R_NAME(name) R_NAME_1 (RELOC_PREFIX, name) 36da0c48c4Sopenharmony_ci#define R_NAME_1(prefix, type) R_NAME_2 (prefix, type) 37da0c48c4Sopenharmony_ci#define R_NAME_2(prefix, type) #prefix #type 38da0c48c4Sopenharmony_ci 39da0c48c4Sopenharmony_ci#define RELOC_TYPES STRINGIFIED_PASTE (BACKEND, reloc.def) 40da0c48c4Sopenharmony_ci#define STRINGIFIED_PASTE(a, b) STRINGIFY (PASTE (a, b)) 41da0c48c4Sopenharmony_ci#define STRINGIFY(x) STRINGIFY_1 (x) 42da0c48c4Sopenharmony_ci#define STRINGIFY_1(x) #x 43da0c48c4Sopenharmony_ci 44da0c48c4Sopenharmony_ci/* Provide a table of reloc type names, in a PIC-friendly fashion. */ 45da0c48c4Sopenharmony_ci 46da0c48c4Sopenharmony_cistatic const struct EBLHOOK(reloc_nametable) 47da0c48c4Sopenharmony_ci{ 48da0c48c4Sopenharmony_ci char zero[1]; 49da0c48c4Sopenharmony_ci#define RELOC_TYPE(type, uses) \ 50da0c48c4Sopenharmony_ci char name_##type[sizeof R_NAME (type)]; 51da0c48c4Sopenharmony_ci#include RELOC_TYPES 52da0c48c4Sopenharmony_ci#undef RELOC_TYPE 53da0c48c4Sopenharmony_ci} EBLHOOK(reloc_nametable) = 54da0c48c4Sopenharmony_ci { 55da0c48c4Sopenharmony_ci { '\0' }, 56da0c48c4Sopenharmony_ci#define RELOC_TYPE(type, uses) R_NAME (type), 57da0c48c4Sopenharmony_ci#include RELOC_TYPES 58da0c48c4Sopenharmony_ci#undef RELOC_TYPE 59da0c48c4Sopenharmony_ci }; 60da0c48c4Sopenharmony_ci#define reloc_namestr (&EBLHOOK(reloc_nametable).zero) 61da0c48c4Sopenharmony_ci 62da0c48c4Sopenharmony_cistatic const uint_fast16_t EBLHOOK(reloc_nameidx)[] = 63da0c48c4Sopenharmony_ci{ 64da0c48c4Sopenharmony_ci#define RELOC_TYPE(type, uses) \ 65da0c48c4Sopenharmony_ci [R_TYPE (type)] = offsetof (struct EBLHOOK(reloc_nametable), name_##type), 66da0c48c4Sopenharmony_ci#include RELOC_TYPES 67da0c48c4Sopenharmony_ci#undef RELOC_TYPE 68da0c48c4Sopenharmony_ci}; 69da0c48c4Sopenharmony_ci#define nreloc \ 70da0c48c4Sopenharmony_ci ((int) (sizeof EBLHOOK(reloc_nameidx) / sizeof EBLHOOK(reloc_nameidx)[0])) 71da0c48c4Sopenharmony_ci 72da0c48c4Sopenharmony_ci#define REL (1 << (ET_REL - 1)) 73da0c48c4Sopenharmony_ci#define EXEC (1 << (ET_EXEC - 1)) 74da0c48c4Sopenharmony_ci#define DYN (1 << (ET_DYN - 1)) 75da0c48c4Sopenharmony_cistatic const uint8_t EBLHOOK(reloc_valid)[] = 76da0c48c4Sopenharmony_ci{ 77da0c48c4Sopenharmony_ci#define RELOC_TYPE(type, uses) [R_TYPE (type)] = uses, 78da0c48c4Sopenharmony_ci#include RELOC_TYPES 79da0c48c4Sopenharmony_ci#undef RELOC_TYPE 80da0c48c4Sopenharmony_ci}; 81da0c48c4Sopenharmony_ci#undef REL 82da0c48c4Sopenharmony_ci#undef EXEC 83da0c48c4Sopenharmony_ci#undef DYN 84da0c48c4Sopenharmony_ci 85da0c48c4Sopenharmony_ciconst char * 86da0c48c4Sopenharmony_ciEBLHOOK(reloc_type_name) (int reloc, 87da0c48c4Sopenharmony_ci char *buf __attribute__ ((unused)), 88da0c48c4Sopenharmony_ci size_t len __attribute__ ((unused))) 89da0c48c4Sopenharmony_ci{ 90da0c48c4Sopenharmony_ci#ifdef RELOC_TYPE_ID 91da0c48c4Sopenharmony_ci reloc = RELOC_TYPE_ID (reloc); 92da0c48c4Sopenharmony_ci#endif 93da0c48c4Sopenharmony_ci 94da0c48c4Sopenharmony_ci if (reloc >= 0 && reloc < nreloc && EBLHOOK(reloc_nameidx)[reloc] != 0) 95da0c48c4Sopenharmony_ci return reloc_namestr[EBLHOOK(reloc_nameidx)[reloc]]; 96da0c48c4Sopenharmony_ci return NULL; 97da0c48c4Sopenharmony_ci} 98da0c48c4Sopenharmony_ci 99da0c48c4Sopenharmony_cibool 100da0c48c4Sopenharmony_ciEBLHOOK(reloc_type_check) (int reloc) 101da0c48c4Sopenharmony_ci{ 102da0c48c4Sopenharmony_ci#ifdef RELOC_TYPE_ID 103da0c48c4Sopenharmony_ci reloc = RELOC_TYPE_ID (reloc); 104da0c48c4Sopenharmony_ci#endif 105da0c48c4Sopenharmony_ci 106da0c48c4Sopenharmony_ci return reloc >= 0 && reloc < nreloc && EBLHOOK(reloc_nameidx)[reloc] != 0; 107da0c48c4Sopenharmony_ci} 108da0c48c4Sopenharmony_ci 109da0c48c4Sopenharmony_cibool 110da0c48c4Sopenharmony_ciEBLHOOK(reloc_valid_use) (Elf *elf, int reloc) 111da0c48c4Sopenharmony_ci{ 112da0c48c4Sopenharmony_ci uint8_t uses; 113da0c48c4Sopenharmony_ci 114da0c48c4Sopenharmony_ci GElf_Ehdr ehdr_mem; 115da0c48c4Sopenharmony_ci GElf_Ehdr *ehdr = gelf_getehdr (elf, &ehdr_mem); 116da0c48c4Sopenharmony_ci assert (ehdr != NULL); 117da0c48c4Sopenharmony_ci uint8_t type = ehdr->e_type; 118da0c48c4Sopenharmony_ci 119da0c48c4Sopenharmony_ci#ifdef RELOC_TYPE_ID 120da0c48c4Sopenharmony_ci reloc = RELOC_TYPE_ID (reloc); 121da0c48c4Sopenharmony_ci#endif 122da0c48c4Sopenharmony_ci 123da0c48c4Sopenharmony_ci uses = EBLHOOK(reloc_valid)[reloc]; 124da0c48c4Sopenharmony_ci return type > ET_NONE && type < ET_CORE && (uses & (1 << (type - 1))); 125da0c48c4Sopenharmony_ci} 126da0c48c4Sopenharmony_ci 127da0c48c4Sopenharmony_ci#ifndef NO_COPY_RELOC 128da0c48c4Sopenharmony_cibool 129da0c48c4Sopenharmony_ciEBLHOOK(copy_reloc_p) (int reloc) 130da0c48c4Sopenharmony_ci{ 131da0c48c4Sopenharmony_ci return reloc == R_TYPE (COPY); 132da0c48c4Sopenharmony_ci} 133da0c48c4Sopenharmony_ci#endif 134da0c48c4Sopenharmony_ci 135da0c48c4Sopenharmony_cibool 136da0c48c4Sopenharmony_ciEBLHOOK(none_reloc_p) (int reloc) 137da0c48c4Sopenharmony_ci{ 138da0c48c4Sopenharmony_ci return reloc == R_TYPE (NONE); 139da0c48c4Sopenharmony_ci} 140da0c48c4Sopenharmony_ci 141da0c48c4Sopenharmony_ci#ifndef NO_RELATIVE_RELOC 142da0c48c4Sopenharmony_cibool 143da0c48c4Sopenharmony_ciEBLHOOK(relative_reloc_p) (int reloc) 144da0c48c4Sopenharmony_ci{ 145da0c48c4Sopenharmony_ci return reloc == R_TYPE (RELATIVE); 146da0c48c4Sopenharmony_ci} 147da0c48c4Sopenharmony_ci#endif 148da0c48c4Sopenharmony_ci 149da0c48c4Sopenharmony_cistatic void 150da0c48c4Sopenharmony_ciEBLHOOK(init_reloc) (Ebl *ebl) 151da0c48c4Sopenharmony_ci{ 152da0c48c4Sopenharmony_ci ebl->reloc_type_name = EBLHOOK(reloc_type_name); 153da0c48c4Sopenharmony_ci ebl->reloc_type_check = EBLHOOK(reloc_type_check); 154da0c48c4Sopenharmony_ci ebl->reloc_valid_use = EBLHOOK(reloc_valid_use); 155da0c48c4Sopenharmony_ci ebl->none_reloc_p = EBLHOOK(none_reloc_p); 156da0c48c4Sopenharmony_ci#ifndef NO_COPY_RELOC 157da0c48c4Sopenharmony_ci ebl->copy_reloc_p = EBLHOOK(copy_reloc_p); 158da0c48c4Sopenharmony_ci#endif 159da0c48c4Sopenharmony_ci#ifndef NO_RELATIVE_RELOC 160da0c48c4Sopenharmony_ci ebl->relative_reloc_p = EBLHOOK(relative_reloc_p); 161da0c48c4Sopenharmony_ci#endif 162da0c48c4Sopenharmony_ci} 163