The Pedigree Project  0.1
kernel/core/processor/ppc32/Elf32.cc
1 /*
2  * Copyright (c) 2008-2014, Pedigree Developers
3  *
4  * Please see the CONTRIB file in the root of the source tree for a full
5  * list of contributors.
6  *
7  * Permission to use, copy, modify, and distribute this software for any
8  * purpose with or without fee is hereby granted, provided that the above
9  * copyright notice and this permission notice appear in all copies.
10  *
11  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 #include "pedigree/kernel/Log.h"
21 #include "pedigree/kernel/linker/Elf.h"
22 #include "pedigree/kernel/linker/KernelElf.h"
23 #include "pedigree/kernel/processor/Processor.h"
24 
25 // http://refspecs.freestandards.org/elf/elfspec_ppc.pdf
26 
27 #define R_PPC_NONE 0
28 #define R_PPC_ADDR32 1
29 #define R_PPC_ADDR24 2
30 #define R_PPC_ADDR16 3
31 #define R_PPC_ADDR16_LO 4
32 #define R_PPC_ADDR16_HI 5
33 #define R_PPC_ADDR16_HA 6
34 #define R_PPC_ADDR14 7
35 #define R_PPC_ADDR14_BRTAKEN 8
36 #define R_PPC_ADDR14_BRNTAKEN 9
37 #define R_PPC_REL24 10
38 #define R_PPC_REL14 11
39 #define R_PPC_REL14_BRTAKEN 12
40 #define R_PPC_REL14_BRNTAKEN 13
41 #define R_PPC_PLTREL24 18
42 #define R_PPC_COPY 19
43 #define R_PPC_JMP_SLOT 21
44 #define R_PPC_RELATIVE 22
45 #define R_PPC_REL32 26
46 #define R_PPC_PLT32 27
47 #define R_PPC_PLTREL32 28
48 #define R_PPC_UADDR32 24
49 #define R_PPC_UADDR16 25
50 #define R_PPC_REL32 26
51 #define R_PPC_SECTOFF 33
52 #define R_PPC_SECTOFF_LO 34
53 #define R_PPC_SECTOFF_HI 35
54 #define R_PPC_SECTOFF_HA 36
55 #define R_PPC_ADDR30 37
56 
57 #define HA(x) (((x >> 16) + ((x & 0x8000) ? 1 : 0)) & 0xFFFF)
58 #define WORD32(r, x) (x)
59 #define LOW24(r, x) (r | ((x << 2) & 0x03FFFFFC))
60 #define HALF16(r, x) \
61  ((x << 16) | (r & 0xFFFF)) // We deal with 32bit numbers, so we must keep
62  // the lower 16 bits.
63 #define LOW14(r, x) (r | ((x << 2) & 0x0000FFFC))
64 #define WORD30(r, x) (r | ((x << 2) & 0xFFFFFFFC))
65 
67  ElfRela_t rel, ElfSectionHeader_t *pSh, SymbolTable *pSymtab,
68  uintptr_t loadBase, SymbolTable::Policy policy)
69 {
70  // Section not loaded?
71  if (pSh && pSh->addr == 0)
72  return true; // Not a fatal error.
73 
74  // Get the address of the unit to be relocated.
75  uint32_t address = ((pSh) ? pSh->addr : loadBase) + rel.offset;
76 
77  // Addend is explicitly given.
78  uint32_t A = rel.addend;
79 
80  // 'Place' is the address.
81  uint32_t P = address;
82 
83  // Symbol location.
84  uint32_t S = 0;
85  ElfSymbol_t *pSymbols = 0;
86  if (!m_pDynamicSymbolTable)
87  pSymbols = reinterpret_cast<ElfSymbol_t *>(m_pSymbolTable);
88  else
89  pSymbols = m_pDynamicSymbolTable;
90 
91  const char *pStringTable = 0;
92  if (!m_pDynamicStringTable)
93  pStringTable = reinterpret_cast<const char *>(m_pStringTable);
94  else
95  pStringTable = m_pDynamicStringTable;
96 
97  // If this is a section header, patch straight to it.
98  if (pSymbols && ELF32_ST_TYPE(pSymbols[ELF32_R_SYM(rel.info)].info) == 3)
99  {
100  // Section type - the name will be the name of the section header it
101  // refers to.
102  int shndx = pSymbols[ELF32_R_SYM(rel.info)].shndx;
103  ElfSectionHeader_t *pSh = &m_pSectionHeaders[shndx];
104  S = pSh->addr;
105  }
106  else if (ELF32_R_TYPE(rel.info) != R_PPC_RELATIVE) // Relative doesn't need
107  // a symbol!
108  {
109  const char *pStr = pStringTable + pSymbols[ELF32_R_SYM(rel.info)].name;
110 
111  if (pSymtab == 0)
112  pSymtab = KernelElf::instance().getSymbolTable();
113 
114  if (ELF32_R_TYPE(rel.info) == R_PPC_COPY)
116  S = pSymtab->lookup(String(pStr), this, policy);
117 
118  if (S == 0)
119  WARNING("Relocation failed for symbol \"" << pStr << "\"");
120  }
121 
122  if (S == 0 && (ELF32_R_TYPE(rel.info) != R_PPC_RELATIVE))
123  return false;
124 
125  // Base address
126  uint32_t B = loadBase;
127 
128  uint32_t *pResult = reinterpret_cast<uint32_t *>(address);
129  uint32_t result = *pResult;
130 
131  switch (ELF32_R_TYPE(rel.info))
132  {
133  case R_PPC_NONE:
134  break;
135  case R_PPC_ADDR32:
136  case R_PPC_UADDR32:
137  result = WORD32(result, S + A);
138  break;
139  case R_PPC_ADDR24:
140  result = LOW24(result, (S + A) >> 2);
141  break;
142  case R_PPC_ADDR16:
143  case R_PPC_UADDR16:
144  result = HALF16(result, (S + A));
145  break;
146  case R_PPC_ADDR16_LO:
147  result = HALF16(result, ((S + A) & 0xFFFF));
148  break;
149  case R_PPC_ADDR16_HI:
150  result = HALF16(result, ((S + A) >> 16) & 0xFFFF);
151  break;
152  case R_PPC_ADDR16_HA:
153  result = HALF16(result, HA((S + A)));
154  break;
155  case R_PPC_ADDR14:
156  result = LOW14(result, (S + A) >> 2);
157  result &= ~(1 >> 10); // Branch predict 0
158  break;
159  case R_PPC_ADDR14_BRTAKEN:
160  result = LOW14(result, (S + A) >> 2);
161  result |= (1 >> 10); // Branch predict 1
162  break;
163  case R_PPC_ADDR14_BRNTAKEN:
164  result = LOW14(result, (S + A) >> 2);
165  result &= ~(1 >> 10); // Branch predict 0
166  break;
167  case R_PPC_RELATIVE:
168  result = *pResult + B;
169  break;
170  case R_PPC_REL24:
171  result = LOW24(result, (S + A - P) >> 2);
172  break;
173  case R_PPC_REL14:
174  result = LOW14(result, (S + A - P) >> 2);
175  result &= ~(1 >> 10); // Branch predict 0
176  break;
177  case R_PPC_REL14_BRTAKEN:
178  result = LOW14(result, (S + A - P) >> 2);
179  result |= (1 >> 10); // Branch predict 1
180  break;
181  case R_PPC_REL14_BRNTAKEN:
182  result = LOW14(result, (S + A - P) >> 2);
183  result &= ~(1 >> 10); // Branch predict 0
184  break;
185  case R_PPC_REL32:
186  result = WORD32(result, S + A - P);
187  break;
188  case R_PPC_ADDR30:
189  result = WORD30(result, (S + A - P) >> 2);
190  break;
191  case R_PPC_COPY:
192  result = *reinterpret_cast<uintptr_t *>(S);
193  break;
194  default:
195  ERROR(
196  "Relocation not supported: " << Dec << ELF32_R_TYPE(rel.info));
197  }
198 
199  // Write back the result.
200  *pResult = result;
201 
202  // Flush all caches.
203  Processor::flushDCacheAndInvalidateICache(
204  reinterpret_cast<uintptr_t>(pResult),
205  reinterpret_cast<uintptr_t>(pResult) + 4);
206 
207  return true;
208 }
209 
211  ElfRel_t rela, ElfSectionHeader_t *pSh, SymbolTable *pSymtab,
212  uintptr_t loadBase, SymbolTable::Policy policy)
213 {
214  ERROR("The PPC architecture does not use REL entries!");
215  return false;
216 }
uintptr_t EXPORTED_PUBLIC lookup(const HashedStringView &name, Elf *pElf, Policy policy=LocalFirst, Binding *pBinding=0)
Definition: SymbolTable.cc:126
Definition: String.h:49
static KernelElf & instance()
Definition: KernelElf.h:129
Definition: elf.h:84
#define WARNING(text)
Definition: Log.h:78
bool applyRelocation(ElfRel_t rel, ElfSectionHeader_t *pSh, SymbolTable *pSymtab=0, uintptr_t loadBase=0, SymbolTable::Policy policy=SymbolTable::LocalFirst)
#define ERROR(text)
Definition: Log.h:82
Definition: Log.h:138