The Pedigree Project  0.1
elf.c
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 "elf.h"
21 #include <stdint.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 
26 Elf_t *elf_create(uint8_t *buffer, size_t len)
27 {
28  Elf_t *elf = (Elf_t *) malloc(sizeof(Elf_t));
29  // The main header will be at buffer[0].
30  elf->header = (ElfHeader_t *) buffer;
31 
32  // Check the ident.
33  if ((elf->header->ident[1] != 'E') || (elf->header->ident[2] != 'L') ||
34  (elf->header->ident[3] != 'F') || (elf->header->ident[0] != 127))
35  {
36  printf("ELF file: ident check failed!");
37  return 0;
38  }
39 
40  // Check the bit-length.
41  if (elf->header->ident[4] != 1)
42  {
43  printf("ELF file: wrong bit length!");
44  return 0;
45  }
46 
47  // Load in the section headers.
48  elf->section_headers = (ElfSectionHeader_t *) malloc(
49  sizeof(ElfSectionHeader_t) * elf->header->shnum);
50  memcpy(
51  (uint8_t *) elf->section_headers, &buffer[elf->header->shoff],
52  elf->header->shnum * sizeof(ElfSectionHeader_t));
53 
54  // Find the section header string table.
55  ElfSectionHeader_t *shstrtab_section =
56  &elf->section_headers[elf->header->shstrndx];
57 
58  // Load the section header string table.
59  char *shstrtab = (char *) malloc(shstrtab_section->size);
60  memcpy(
61  (uint8_t *) shstrtab, &buffer[shstrtab_section->offset],
62  shstrtab_section->size);
63 
64  ElfSectionHeader_t *symtab = 0, *strtab = 0;
65  // Go through each section header, trying to find .symtab.
66  for (int i = 0; i < elf->header->shnum; i++)
67  {
68  const char *str = shstrtab + elf->section_headers[i].name;
69  if (!strcmp(str, ".symtab"))
70  symtab = &elf->section_headers[i];
71  if (!strcmp(str, ".strtab"))
72  strtab = &elf->section_headers[i];
73  }
74 
75  if (symtab == 0)
76  {
77  printf("ELF: symbol table not found!");
78  return 0;
79  }
80  else
81  {
82  elf->symtabsz = symtab->size / sizeof(ElfSymbol_t);
83  elf->symtab = (ElfSymbol_t *) malloc(symtab->size);
84  memcpy((uint8_t *) elf->symtab, &buffer[symtab->offset], symtab->size);
85  }
86 
87  if (strtab == 0)
88  {
89  printf("ELF: string table not found!");
90  return 0;
91  }
92  else
93  {
94  elf->strtabsz = strtab->size;
95  elf->strtab = (char *) malloc(strtab->size);
96  memcpy((uint8_t *) elf->strtab, &buffer[strtab->offset], strtab->size);
97  }
98 
99  elf->buffer = buffer;
100 
101  return elf;
102 }
103 
104 ElfSymbol_t *elf_get_symbol(Elf_t *elf, const char *name)
105 {
106  for (size_t i = 0; i < elf->symtabsz; i++)
107  if (!strcmp((char *) (elf->strtab + elf->symtab[i].name), name))
108  return &(elf->symtab[i]);
109  return 0;
110 }
111 
112 uint8_t *elf_relptr(Elf_t *elf, ElfSymbol_t *sym, uint32_t ptr)
113 {
114  ElfSectionHeader_t *relsh = 0;
115  for (size_t i = 0; i < elf->header->shnum; i++)
116  {
117  if (elf->section_headers[i].type == SHT_REL &&
118  elf->section_headers[i].info == sym->shndx)
119  {
120  relsh = &(elf->section_headers[i]);
121  break;
122  }
123  }
124  if (!relsh)
125  return 0;
126  ElfRel_t *rel = 0;
127  for (size_t i = 0; i < (relsh->size / sizeof(ElfRel_t)); i++)
128  {
129  ElfRel_t *tmp =
130  (ElfRel_t *) &(elf->buffer[relsh->offset + i * sizeof(ElfRel_t)]);
131  if (tmp->offset == sym->value)
132  {
133  rel = tmp;
134  break;
135  }
136  }
137  if (!rel)
138  return 0;
139  ElfSymbol_t *relsym = &(elf->symtab[R_SYM(rel->info)]);
140  if (ST_TYPE(relsym->info) != 3)
141  return 0;
142  return &elf->buffer[elf->section_headers[relsym->shndx].offset + ptr];
143 }
Definition: elf.h:84
Definition: elf.h:90