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