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