41 #include "loader/elf32.h"
42 #include "loader/cle.h"
43 #include "loader/sym.h"
46 #include "lib/assert.h"
49 #define PRINTF(...) do {} while (0)
51 #define PRINTF(...) printf(__VA_ARGS__)
71 cle_read_info(
struct cle_info *info,
72 int (*pread)(
void *,
int, off_t),
81 struct elf32_ehdr ehdr;
82 struct elf32_shdr shdr;
84 #define ehdr huge.ehdr
85 #define shdr huge.shdr
91 cle_word strtabsize = 0;
94 memset(info, 0x0,
sizeof(*info));
96 ret = pread(&ehdr,
sizeof(ehdr), hdr);
100 if(memcmp(ehdr.e_ident, ELF_MAGIC_HEADER, ELF_MAGIC_HEADER_SIZE) != 0) {
101 return CLE_BAD_HEADER;
104 shoff = hdr + ehdr.e_shoff;
105 shentsize = ehdr.e_shentsize;
106 shnum = ehdr.e_shnum;
109 ret = pread(&shdr,
sizeof(shdr), shoff + shentsize*ehdr.e_shstrndx);
119 strs = shdr.sh_offset;
135 for(i = 0; i < shnum; ++i) {
136 ret = pread(&shdr,
sizeof(shdr), shoff);
140 ret = pread(info->name,
sizeof(info->name), hdr + strs + shdr.sh_name);
143 if(strncmp(info->name,
".text", 5) == 0) {
144 info->textoff = shdr.sh_offset;
145 info->textsize = shdr.sh_size;
146 info->text_shndx = i;
147 }
else if(strncmp(info->name,
".rela.text", 10) == 0) {
148 info->textrelaoff = shdr.sh_offset;
149 info->textrelasize = shdr.sh_size;
150 }
else if(strncmp(info->name,
".data", 5) == 0) {
151 info->dataoff = shdr.sh_offset;
152 info->datasize = shdr.sh_size;
153 info->data_shndx = i;
154 }
else if(strncmp(info->name,
".rela.data", 10) == 0) {
155 info->datarelaoff = shdr.sh_offset;
156 info->datarelasize = shdr.sh_size;
157 }
else if(strncmp(info->name,
".symtab", 7) == 0) {
158 info->symtaboff = shdr.sh_offset;
159 info->symtabsize = shdr.sh_size;
160 }
else if(strncmp(info->name,
".strtab", 7) == 0) {
161 info->strtaboff = shdr.sh_offset;
162 strtabsize = shdr.sh_size;
163 }
else if(strncmp(info->name,
".bss", 4) == 0) {
164 info->bsssize = shdr.sh_size;
167 info->name[
sizeof(info->name) - 1] = 0;
168 PRINTF(
"cle: unknown section %.12s\n", info->name);
175 if(info->symtabsize == 0) {
176 return CLE_NO_SYMTAB;
178 if(strtabsize == 0) {
179 return CLE_NO_STRTAB;
181 if(info->textsize == 0) {
197 cle_relocate(
struct cle_info *info,
198 int (*pread)(
void *,
int, off_t),
204 struct elf32_rela rela;
210 for(off = hdr + reloff;
211 off < hdr + reloff + relsize;
212 off +=
sizeof(
struct elf32_rela)) {
213 ret = pread(&rela,
sizeof(rela), off);
215 ret = pread(&s,
sizeof(s),
216 hdr + info->symtaboff
217 +
sizeof(
struct elf32_sym)*ELF32_R_SYM(rela.r_info));
220 if(s.st_shndx == info->bss_shndx) {
221 addr = (cle_addr)(uintptr_t)info->bss;
222 }
else if(s.st_shndx == info->data_shndx) {
223 addr = (cle_addr)(uintptr_t)info->data;
224 }
else if(s.st_shndx == info->text_shndx) {
232 return CLE_UNKNOWN_SEGMENT;
235 ret = pread(info->name,
sizeof(info->name),
236 hdr + info->strtaboff + s.st_name);
238 cle_addr sym = (cle_addr)(uintptr_t)sym_function(info->name);
244 sym = (cle_addr)(uintptr_t)sym_object(info->name);
246 if(addr == NOLL && sym != NOLL) {
248 }
else if(addr != NOLL && sym == NOLL) {
249 addr = addr + s.st_value;
250 }
else if(addr == NOLL && sym == NOLL) {
251 PRINTF(
"cle: undefined reference to %.32s (%d)\n",
252 info->name, s.st_info);
253 return CLE_UNDEFINED;
254 }
else if(addr != NOLL && sym != NOLL) {
255 PRINTF(
"cle: multiple definitions of %.32s (%d)\n",
256 info->name, s.st_info);
257 return CLE_MULTIPLY_DEFINED;
261 addr += rela.r_addend;
263 ret = cle_write_reloc(segmem + rela.r_offset, &rela, addr, info);
277 cle_lookup(
struct cle_info *info,
278 int (*pread)(
void *,
int, off_t),
288 for(a = hdr + info->symtaboff;
289 a < hdr + info->symtaboff + info->symtabsize;
291 ret = pread(&s,
sizeof(s), a);
295 ret = pread(info->name,
sizeof(info->name),
296 hdr + info->strtaboff + s.st_name);
299 if(strcmp(info->name, symbol) == 0) {
300 if(s.st_shndx == info->bss_shndx) {
301 addr = (cle_addr)(uintptr_t)info->bss;
302 }
else if(s.st_shndx == info->data_shndx) {
303 addr = (cle_addr)(uintptr_t)info->data;
304 }
else if(s.st_shndx == info->text_shndx) {
307 return (
void *)(uintptr_t)((addr + s.st_value) >> 1);
313 return (
void *)(uintptr_t)(addr + s.st_value);