41 #include "loader/symtab.h"
49 #define PRINTF(...) printf(__VA_ARGS__)
51 #define PRINTF(...) do {} while (0)
58 unsigned char e_ident[EI_NIDENT];
67 elf32_half e_phentsize;
69 elf32_half e_shentsize;
71 elf32_half e_shstrndx;
90 elf32_word sh_addralign;
91 elf32_word sh_entsize;
96 #define SHT_PROGBITS 1
101 #define SHT_DYNAMIC 6
106 #define SHT_DYNSYM 11
107 #define SHT_LOPROC 0x70000000
108 #define SHT_HIPROC 0x7fffffff
109 #define SHT_LOUSER 0x80000000
110 #define SHT_HIUSER 0xffffffff
121 unsigned char st_info;
122 unsigned char st_other;
126 #define ELF32_R_SYM(info) ((info) >> 8)
127 #define ELF32_R_TYPE(info) ((unsigned char)(info))
129 struct relevant_section {
130 unsigned char number;
139 static struct relevant_section bss, data, rodata, text;
141 const static unsigned char elf_magic_header[] =
142 {0x7f, 0x45, 0x4c, 0x46,
150 copy_segment_data(
int input_fd,
unsigned int offset,
156 while(len >
sizeof(buffer)) {
157 res = cfs_read(input_fd, buffer,
sizeof(buffer));
159 res = elfloader_output_write_segment(output, buffer,
sizeof(buffer));
161 len -=
sizeof(buffer);
163 res = cfs_read(input_fd, buffer, len);
165 res = elfloader_output_write_segment(output, buffer, len);
171 seek_read(
int fd,
unsigned int offset,
char *buf,
int len)
174 return cfs_read(fd, buf, len);
178 find_local_symbol(
int input_fd,
const char *symbol,
179 unsigned int symtab,
unsigned short symtabsize,
185 struct relevant_section *sect;
188 for(a = symtab; a < symtab + symtabsize; a +=
sizeof(s)) {
189 ret = seek_read(input_fd, a, (
char *)&s,
sizeof(s));
190 if (ret < 0)
return NULL;
193 ret = seek_read(input_fd, strtab + s.st_name, name,
sizeof(name));
194 if (ret < 0)
return NULL;
196 if(strcmp(name, symbol) == 0) {
197 if(s.st_shndx == bss.number) {
199 }
else if(s.st_shndx == data.number) {
201 }
else if(s.st_shndx == text.number) {
206 return &(sect->address[s.st_value]);
214 relocate_section(
int input_fd,
216 unsigned int section,
unsigned short size,
217 unsigned int sectionaddr,
221 unsigned int symtab,
unsigned short symtabsize,
222 unsigned char using_relas)
225 struct elf32_rela rela;
231 struct relevant_section *sect;
236 rel_size =
sizeof(
struct elf32_rela);
238 rel_size =
sizeof(
struct elf32_rel);
241 for(a = section; a < section + size; a += rel_size) {
242 ret = seek_read(input_fd, a, (
char *)&rela, rel_size);
244 ret = seek_read(input_fd,
246 sizeof(
struct elf32_sym) * ELF32_R_SYM(rela.r_info)),
247 (
char *)&s,
sizeof(s));
250 ret = seek_read(input_fd, strtab + s.st_name, name,
sizeof(name));
252 PRINTF(
"name: %s\n", name);
253 addr = (
char *)symtab_lookup(name);
256 PRINTF(
"name not found in global: %s\n", name);
257 addr = find_local_symbol(input_fd, name, symtab, symtabsize, strtab);
258 PRINTF(
"found address %p\n", addr);
261 if(s.st_shndx == bss.number) {
263 }
else if(s.st_shndx == data.number) {
265 }
else if(s.st_shndx == rodata.number) {
267 }
else if(s.st_shndx == text.number) {
270 PRINTF(
"elfloader unknown name: '%30s'\n", name);
275 addr = sect->address;
278 if(s.st_shndx == bss.number) {
280 }
else if(s.st_shndx == data.number) {
282 }
else if(s.st_shndx == rodata.number) {
284 }
else if(s.st_shndx == text.number) {
290 addr = sect->address;
297 ret = seek_read(fd, sectionaddr + rela.r_offset, &rela.r_addend, 4);
303 unsigned int offset = elfloader_output_segment_offset(output);
304 if (rela.r_offset < offset) {
305 PRINTF(
"elfloader relocation out of offset order\n");
308 if (rela.r_offset > offset) {
309 ret = copy_segment_data(input_fd, offset+sectionaddr, output,
310 rela.r_offset - offset);
322 find_program_processes(
int input_fd,
323 unsigned int symtab,
unsigned short size,
330 for(a = symtab; a < symtab + size; a +=
sizeof(s)) {
331 seek_read(input_fd, a, (
char *)&s,
sizeof(s));
334 seek_read(input_fd, strtab + s.st_name, name,
sizeof(name));
335 if(strcmp(name,
"autostart_processes") == 0) {
336 return &data.address[s.st_value];
352 print_chars(
unsigned char *ptr,
int num)
355 for(i = 0; i < num; ++i) {
356 PRINTF(
"%d", ptr[i]);
367 copy_segment(
int input_fd,
369 unsigned int section,
unsigned short size,
370 unsigned int sectionaddr,
374 unsigned int symtab,
unsigned short symtabsize,
375 unsigned char using_relas,
376 unsigned int seg_size,
unsigned int seg_type)
380 ret = elfloader_output_start_segment(output, seg_type,sectionbase, seg_size);
382 ret = relocate_section(input_fd, output,
388 symtab, symtabsize, using_relas);
390 offset = elfloader_output_segment_offset(output);
391 ret = copy_segment_data(input_fd, offset+sectionaddr, output,seg_size - offset);
393 return elfloader_output_end_segment(output);
400 struct elf32_ehdr ehdr;
401 struct elf32_shdr shdr;
402 struct elf32_shdr strtable;
404 unsigned int shdrptr;
405 unsigned int nameptr;
409 unsigned short shdrnum, shdrsize;
411 unsigned char using_relas = -1;
412 unsigned short textoff = 0, textsize, textrelaoff = 0, textrelasize;
413 unsigned short dataoff = 0, datasize, datarelaoff = 0, datarelasize;
414 unsigned short rodataoff = 0, rodatasize, rodatarelaoff = 0, rodatarelasize;
415 unsigned short symtaboff = 0, symtabsize;
416 unsigned short strtaboff = 0, strtabsize;
417 unsigned short bsssize = 0;
419 struct process **process;
425 ret = seek_read(input_fd, 0, (
char *)&ehdr,
sizeof(ehdr));
431 if(memcmp(ehdr.e_ident, elf_magic_header,
sizeof(elf_magic_header)) != 0) {
432 PRINTF(
"ELF header problems\n");
437 shdrptr = ehdr.e_shoff;
438 ret = seek_read(input_fd, shdrptr, (
char *)&shdr,
sizeof(shdr));
442 shdrsize = ehdr.e_shentsize;
443 shdrnum = ehdr.e_shnum;
446 ret = seek_read(input_fd, ehdr.e_shoff + shdrsize * ehdr.e_shstrndx,
447 (
char *)&strtable,
sizeof(strtable));
453 strs = strtable.sh_offset;
473 textsize = textrelasize = datasize = datarelasize =
474 rodatasize = rodatarelasize = symtabsize = strtabsize = 0;
476 bss.number = data.number = rodata.number = text.number = -1;
478 shdrptr = ehdr.e_shoff;
479 for(i = 0; i < shdrnum; ++i) {
481 ret = seek_read(input_fd, shdrptr, (
char *)&shdr,
sizeof(shdr));
485 nameptr = strs + shdr.sh_name;
486 ret = seek_read(input_fd, nameptr, name,
sizeof(name));
494 if(strncmp(name,
".text", 5) == 0) {
495 textoff = shdr.sh_offset;
496 textsize = shdr.sh_size;
498 text.offset = textoff;
499 }
else if(strncmp(name,
".rel.text", 9) == 0) {
501 textrelaoff = shdr.sh_offset;
502 textrelasize = shdr.sh_size;
503 }
else if(strncmp(name,
".rela.text", 10) == 0) {
505 textrelaoff = shdr.sh_offset;
506 textrelasize = shdr.sh_size;
507 }
else if(strncmp(name,
".data", 5) == 0) {
508 dataoff = shdr.sh_offset;
509 datasize = shdr.sh_size;
511 data.offset = dataoff;
512 }
else if(strncmp(name,
".rodata", 7) == 0) {
514 rodataoff = shdr.sh_offset;
515 rodatasize = shdr.sh_size;
517 rodata.offset = rodataoff;
518 }
else if(strncmp(name,
".rel.rodata", 11) == 0) {
521 rodatarelaoff = shdr.sh_offset;
522 rodatarelasize = shdr.sh_size;
523 }
else if(strncmp(name,
".rela.rodata", 12) == 0) {
525 rodatarelaoff = shdr.sh_offset;
526 rodatarelasize = shdr.sh_size;
527 }
else if(strncmp(name,
".rel.data", 9) == 0) {
530 datarelaoff = shdr.sh_offset;
531 datarelasize = shdr.sh_size;
532 }
else if(strncmp(name,
".rela.data", 10) == 0) {
534 datarelaoff = shdr.sh_offset;
535 datarelasize = shdr.sh_size;
536 }
else if(strncmp(name,
".symtab", 7) == 0) {
537 symtaboff = shdr.sh_offset;
538 symtabsize = shdr.sh_size;
539 }
else if(strncmp(name,
".strtab", 7) == 0) {
540 strtaboff = shdr.sh_offset;
541 strtabsize = shdr.sh_size;
542 }
else if(strncmp(name,
".bss", 4) == 0) {
543 bsssize = shdr.sh_size;
552 if(symtabsize == 0) {
555 if(strtabsize == 0) {
564 bss.address = (
char *)
565 elfloader_output_alloc_segment(output, ELFLOADER_SEG_BSS, bsssize);
569 data.address = (
char *)
570 elfloader_output_alloc_segment(output,ELFLOADER_SEG_DATA,datasize);
574 text.address = (
char *)
575 elfloader_output_alloc_segment(output,ELFLOADER_SEG_TEXT,textsize);
579 rodata.address = (
char *)
580 elfloader_output_alloc_segment(output,ELFLOADER_SEG_RODATA,rodatasize);
591 PRINTF(
"elfloader: relocate text\n");
592 if(textrelasize > 0) {
593 ret = copy_segment(input_fd, output,
594 textrelaoff, textrelasize,
599 symtaboff, symtabsize, using_relas,
600 textsize, ELFLOADER_SEG_TEXT);
607 PRINTF(
"elfloader: relocate rodata\n");
608 if(rodatarelasize > 0) {
609 ret = copy_segment(input_fd, output,
610 rodatarelaoff, rodatarelasize,
615 symtaboff, symtabsize, using_relas,
616 rodatasize, ELFLOADER_SEG_RODATA);
618 PRINTF(
"elfloader: data failed\n");
624 PRINTF(
"elfloader: relocate data\n");
625 if(datarelasize > 0) {
626 ret = copy_segment(input_fd, output,
627 datarelaoff, datarelasize,
632 symtaboff, symtabsize, using_relas,
633 datasize, ELFLOADER_SEG_DATA);
635 PRINTF(
"elfloader: data failed\n");
638 ret = elfloader_output_end_segment(output);
651 unsigned int len = bsssize;
652 static const char zeros[16] = {0};
653 ret = elfloader_output_start_segment(output, ELFLOADER_SEG_BSS,
654 bss.address,bsssize);
656 while(len >
sizeof(zeros)) {
657 ret = elfloader_output_write_segment(output, zeros,
sizeof(zeros));
659 len -=
sizeof(zeros);
661 ret = elfloader_output_write_segment(output, zeros, len);
665 PRINTF(
"elfloader: autostart search\n");
666 process = find_local_symbol(input_fd,
"autostart_processes", symtaboff, symtabsize, strtaboff);
667 if(process !=
NULL) {
668 PRINTF(
"elfloader: autostart found\n");
672 PRINTF(
"elfloader: no autostart\n");
673 process = find_program_processes(input_fd, symtaboff, symtabsize, strtaboff);
674 if(process !=
NULL) {
675 PRINTF(
"elfloader: FOUND PRG\n");