The Pedigree Project  0.1
boot/ppc/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 "Elf32.h"
21 #include "prom.h"
22 // include <utilities/utility.h>
23 extern void writeStr(const char *str);
24 int StringCopyN(char *dest, const char *src, int len)
25 {
26  while (*src && len)
27  {
28  *dest++ = *src++;
29  len--;
30  }
31  *dest = '\0';
32  return 0;
33 }
34 int ByteSet(void *buf, int c, size_t len)
35 {
36  unsigned char *tmp = reinterpret_cast<unsigned char *>(buf);
37  while (len--)
38  {
39  *tmp++ = c;
40  }
41  return 0;
42 }
43 
44 void MemoryCopy(void *dest, const void *src, size_t len)
45 {
46  const unsigned char *sp = reinterpret_cast<const unsigned char *>(src);
47  unsigned char *dp = reinterpret_cast<unsigned char *>(dest);
48  for (; len != 0; len--)
49  *dp++ = *sp++;
50 }
51 
52 int StringCompare(const char *p1, const char *p2)
53 {
54  int i = 0;
55  int failed = 0;
56  while (p1[i] != '\0' && p2[i] != '\0')
57  {
58  if (p1[i] != p2[i])
59  {
60  failed = 1;
61  break;
62  }
63  i++;
64  }
65  // why did the loop exit?
66  if ((p1[i] == '\0' && p2[i] != '\0') || (p1[i] != '\0' && p2[i] == '\0'))
67  failed = 1;
68 
69  return failed;
70 }
71 
72 Elf32::Elf32(const char *name)
73  : m_pHeader(0), m_pSymbolTable(0), m_pStringTable(0), m_pShstrtab(0),
74  m_pGotTable(0), m_pRelTable(0), m_pSectionHeaders(0), m_pBuffer(0)
75 {
76  StringCopyN(m_pId, name, 127);
77 }
78 
80 {
81 }
82 
83 bool Elf32::load(uint8_t *pBuffer, unsigned int nBufferLength)
84 {
85  // The main header will be at pBuffer[0].
86  m_pHeader = reinterpret_cast<Elf32Header_t *>(pBuffer);
87 
88  // Check the ident.
89  if ((m_pHeader->ident[1] != 'E') || (m_pHeader->ident[2] != 'L') ||
90  (m_pHeader->ident[3] != 'F') || (m_pHeader->ident[0] != 127))
91  {
92  m_pHeader = 0;
93  return false;
94  }
95 
96  // Load in the section headers.
97  m_pSectionHeaders =
98  reinterpret_cast<Elf32SectionHeader_t *>(&pBuffer[m_pHeader->shoff]);
99 
100  // Find the string tab&pBuffer[m_pStringTable->offset];le.
101  m_pStringTable = &m_pSectionHeaders[m_pHeader->shstrndx];
102 
103  // Temporarily load the string table.
104  const char *pStrtab =
105  reinterpret_cast<const char *>(&pBuffer[m_pStringTable->offset]);
106 
107  // Go through each section header, trying to find .symtab.
108  for (int i = 0; i < m_pHeader->shnum; i++)
109  {
110  const char *pStr = pStrtab + m_pSectionHeaders[i].name;
111  if (!StringCompare(pStr, ".symtab"))
112  {
113  m_pSymbolTable = &m_pSectionHeaders[i];
114  }
115  if (!StringCompare(pStr, ".strtab"))
116  m_pStringTable = &m_pSectionHeaders[i];
117  }
118 
119  m_pBuffer = pBuffer;
120 
121  // Success.
122  return true;
123 }
124 
125 // bool Elf32::load(BootstrapInfo *pBootstrap)
126 // {
127 // // Firstly get the section header string table.
128 // m_pShstrtab = reinterpret_cast<Elf32SectionHeader_t *>(
129 // pBootstrap->getSectionHeader(
130 // pBootstrap->getStringTable()
131 // ));
132 //
133 // // Normally we will try to use the sectionHeader->offset member to access
134 // data, so an
135 // // Elf section's data can be accessed without being mapped into virtual
136 // memory. However,
137 // // when GRUB loads us, it doesn't tell us where exactly ->offset is with
138 // respect to, so here
139 // // we fix offset = addr, then we work w.r.t 0x00.
140 //
141 // // Temporarily load the string table.
142 // const char *pStrtab = reinterpret_cast<const char *>(m_pShstrtab->addr);
143 //
144 // // Now search for the symbol table.
145 // for (int i = 0; i < pBootstrap->getSectionHeaderCount(); i++)
146 // {
147 // Elf32SectionHeader_t *pSh = reinterpret_cast<Elf32SectionHeader_t
148 // *>(pBootstrap->getSectionHeader(i)); const char *pStr = pStrtab +
149 // pSh->name;
150 //
151 // if (pSh->type == SHT_SYMTAB)
152 // {
153 // m_pSymbolTable = pSh;
154 // m_pSymbolTable->offset = m_pSymbolTable->addr;
155 // }
156 // else if (!StringCompare(pStr, ".strtab"))
157 // {
158 // m_pStringTable = pSh;
159 // m_pStringTable->offset = m_pStringTable->addr;
160 // }
161 // }
162 //
163 // return true;
164 // }
165 
167 {
168  unsigned int physAddress = 0x1000000;
169  for (int i = 0; i < m_pHeader->shnum; i++)
170  {
171  if (m_pSectionHeaders[i].flags & SHF_ALLOC)
172  {
173  if (m_pSectionHeaders[i].type != SHT_NOBITS)
174  {
175  prom_map(
176  physAddress, m_pSectionHeaders[i].addr,
177  m_pSectionHeaders[i].size + 0x1000);
178  physAddress += m_pSectionHeaders[i].size + 0x1000;
179  // Copy section data from the file.
180  MemoryCopy(
181  reinterpret_cast<uint8_t *>(m_pSectionHeaders[i].addr),
182  &m_pBuffer[m_pSectionHeaders[i].offset],
183  m_pSectionHeaders[i].size);
184  }
185  else
186  {
187  prom_map(
188  physAddress, m_pSectionHeaders[i].addr,
189  m_pSectionHeaders[i].size + 0x1000);
190  physAddress += m_pSectionHeaders[i].size + 0x1000;
191  ByteSet(
192  reinterpret_cast<uint8_t *>(m_pSectionHeaders[i].addr), 0,
193  m_pSectionHeaders[i].size);
194  }
195  for (unsigned int j = m_pSectionHeaders[i].addr;
196  j < m_pSectionHeaders[i].addr + m_pSectionHeaders[i].size;
197  j += 4)
198  {
199  asm volatile("dcbst 0, %0" ::"r"(j));
200  }
201 
202  asm volatile("sync");
203  for (unsigned int j = m_pSectionHeaders[i].addr;
204  j < m_pSectionHeaders[i].addr + m_pSectionHeaders[i].size;
205  j += 4)
206  {
207  asm volatile("icbi 0, %0" ::"r"(j));
208  }
209  asm volatile("sync;isync;");
210  }
211  }
212  return true;
213 }
214 
215 unsigned int Elf32::getLastAddress()
216 {
217  return 0;
218 }
219 
220 const char *Elf32::lookupSymbol(unsigned int addr, unsigned int *startAddr)
221 {
222  if (!m_pSymbolTable || !m_pStringTable)
223  return 0; // Just return null if we haven't got a symbol table.
224 
225  Elf32Symbol_t *pSymbol =
226  reinterpret_cast<Elf32Symbol_t *>(&m_pBuffer[m_pSymbolTable->offset]);
227  const char *pStrtab =
228  reinterpret_cast<const char *>(&m_pBuffer[m_pStringTable->offset]);
229 
230  for (size_t i = 0; i < m_pSymbolTable->size / sizeof(Elf32Symbol_t); i++)
231  {
232  // Make sure we're looking at an object or function.
233  if (ELF32_ST_TYPE(pSymbol->info) != 0x2 /* function */ &&
234  ELF32_ST_TYPE(pSymbol->info) != 0x0 /* notype (asm functions) */)
235  {
236  pSymbol++;
237  continue;
238  }
239 
240  // If we're checking for a symbol that is apparently zero-sized, add one
241  // so we can actually count it!
242  uint32_t size = pSymbol->size;
243  if (size == 0)
244  size = 1;
245  if ((addr >= pSymbol->value) && (addr < (pSymbol->value + size)))
246  {
247  const char *pStr = pStrtab + pSymbol->name;
248  if (startAddr)
249  *startAddr = pSymbol->value;
250  return pStr;
251  }
252  pSymbol++;
253  }
254  return 0;
255 }
256 
257 uint32_t Elf32::lookupDynamicSymbolAddress(uint32_t off)
258 {
259  return 0;
260 }
261 
262 char *Elf32::lookupDynamicSymbolName(uint32_t off)
263 {
264  return 0;
265 }
266 
268 {
269  return 0;
270 }
271 
272 uint32_t Elf32::getEntryPoint()
273 {
274  return m_pHeader->entry;
275 }
unsigned int getLastAddress()
uint32_t getGlobalOffsetTable()
const char * lookupSymbol(unsigned int addr, unsigned int *startAddr=0)
char * lookupDynamicSymbolName(uint32_t off)
uint32_t lookupDynamicSymbolAddress(uint32_t off)
Elf32(const char *name)
uint32_t getEntryPoint()
uint8_t * m_pBuffer
Offset of the file in memory.
Definition: arm/Elf32.h:217
bool load(uint8_t *pBuffer, unsigned int nBufferLength)
bool writeSections()