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