1 /*-------------------------------------------------------------------------
2 lkelf.c - Create an executable ELF/DWARF file
4 Written By - Erik Petrich, epetrich@users.sourceforge.net (2004)
6 This program is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the
8 Free Software Foundation; either version 2, or (at your option) any
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 -------------------------------------------------------------------------*/
29 # ifdef __MINGW32__ /* GCC MINGW32 depends on configure */
30 # include "sdccconf.h"
34 #else /* Assume Un*x style system */
35 # include "sdccconf.h"
38 static int execStartMSB;
39 static int execStartLSB;
40 static char execStartMSBfound;
41 static char execStartLSBfound;
43 typedef TYPE_UDWORD Elf32_Addr;
44 typedef TYPE_WORD Elf32_Half;
45 typedef TYPE_UDWORD Elf32_Off;
46 typedef TYPE_DWORD Elf32_Sword;
47 typedef TYPE_UDWORD Elf32_Word;
79 /* These e_machine values are from "Motorola 8- and 16-bit Embedded */
80 /* Application Binary Interface (M8/16EABI)" version 2.0 */
129 SHF_WRITE = (1 << 0),
130 SHF_ALLOC = (1 << 1),
131 SHF_EXECINSTR = (1 << 2),
149 unsigned char e_ident[EI_NIDENT];
151 Elf32_Half e_machine;
152 Elf32_Word e_version;
158 Elf32_Half e_phentsize;
160 Elf32_Half e_shentsize;
162 Elf32_Half e_shstrndx;
175 Elf32_Word sh_addralign;
176 Elf32_Word sh_entsize;
191 typedef struct strtabString
194 struct strtabString * prev;
195 struct strtabString * next;
201 strtabString * first;
205 static strtabList shstrtab;
208 typedef struct listEntry
211 struct listEntry * prev;
212 struct listEntry * next;
225 listAdd (listHeader * lhp, void * item)
229 lep = new (sizeof (*lep));
231 lep->prev = lhp->last;
233 lep->prev->next = lep;
247 lhp = new (sizeof (*lhp));
255 strtabFind (strtabList * strtab, char * str)
262 if (!strcmp (str, sp->string))
271 /*-------------------------------------------------------------------*/
272 /* strtabFindOrAdd - Finds a string in a string table or adds the */
273 /* string if it does not already exist. Returns the offset of the */
274 /* string in the table. */
275 /*-------------------------------------------------------------------*/
277 strtabFindOrAdd (strtabList * strtab, char * str)
284 if (!strcmp (str, sp->string))
289 sp = new (sizeof(*sp));
291 sp->index = strtab->last->index + 1 + strlen (strtab->last->string);
294 sp->string = new (1+strlen (str));
295 strcpy (sp->string, str);
297 sp->prev = strtab->last;
307 /*-------------------------------------------------------------------*/
308 /* fputElfStrtab - writes a string table to a file */
309 /*-------------------------------------------------------------------*/
311 fputElfStrtab (strtabList *strtab, FILE *fp)
315 fputc (0, fp); /* index 0 must be the null character */
320 fputs (sp->string, fp);
326 /*-------------------------------------------------------------------*/
327 /* fputElf32_Word - writes an Elf32_Word value to a file */
328 /*-------------------------------------------------------------------*/
330 fputElf32_Word (Elf32_Word x, FILE *fp)
334 fputc (x & 0xff, fp);
335 fputc ((x >> 8) & 0xff, fp);
336 fputc ((x >> 16) & 0xff, fp);
337 fputc ((x >> 24) & 0xff, fp);
341 fputc ((x >> 24) & 0xff, fp);
342 fputc ((x >> 16) & 0xff, fp);
343 fputc ((x >> 8) & 0xff, fp);
344 fputc (x & 0xff, fp);
348 /*-------------------------------------------------------------------*/
349 /* fputElf32_Off - writes an Elf32_Off value to a file */
350 /*-------------------------------------------------------------------*/
352 fputElf32_Off (Elf32_Off x, FILE *fp)
356 fputc (x & 0xff, fp);
357 fputc ((x >> 8) & 0xff, fp);
358 fputc ((x >> 16) & 0xff, fp);
359 fputc ((x >> 24) & 0xff, fp);
363 fputc ((x >> 24) & 0xff, fp);
364 fputc ((x >> 16) & 0xff, fp);
365 fputc ((x >> 8) & 0xff, fp);
366 fputc (x & 0xff, fp);
370 /*-------------------------------------------------------------------*/
371 /* fputElf32_Addr - writes an Elf32_Addr value to a file */
372 /*-------------------------------------------------------------------*/
374 fputElf32_Addr (Elf32_Addr x, FILE *fp)
378 fputc (x & 0xff, fp);
379 fputc ((x >> 8) & 0xff, fp);
380 fputc ((x >> 16) & 0xff, fp);
381 fputc ((x >> 24) & 0xff, fp);
385 fputc ((x >> 24) & 0xff, fp);
386 fputc ((x >> 16) & 0xff, fp);
387 fputc ((x >> 8) & 0xff, fp);
388 fputc (x & 0xff, fp);
392 /*-------------------------------------------------------------------*/
393 /* fputElf32_Half - writes an Elf32_Half value to a file */
394 /*-------------------------------------------------------------------*/
396 fputElf32_Half (Elf32_Half x, FILE *fp)
400 fputc (x & 0xff, fp);
401 fputc ((x >> 8) & 0xff, fp);
405 fputc ((x >> 8) & 0xff, fp);
406 fputc (x & 0xff, fp);
410 /*------------------------------------------------------------------------*/
411 /* fputElf32_Ehdr - writes an Elf32_Ehdr struct (ELF header) to a file */
412 /*------------------------------------------------------------------------*/
414 fputElf32_Ehdr (Elf32_Ehdr * ehdr, FILE * fp)
418 for (i=0; i<EI_NIDENT; i++)
419 fputc (ehdr->e_ident[i], fp);
421 fputElf32_Half (ehdr->e_type, fp);
422 fputElf32_Half (ehdr->e_machine, fp);
423 fputElf32_Word (ehdr->e_version, fp);
424 fputElf32_Addr (ehdr->e_entry, fp);
425 fputElf32_Off (ehdr->e_phoff, fp);
426 fputElf32_Off (ehdr->e_shoff, fp);
427 fputElf32_Word (ehdr->e_flags, fp);
428 fputElf32_Half (ehdr->e_ehsize, fp);
429 fputElf32_Half (ehdr->e_phentsize, fp);
430 fputElf32_Half (ehdr->e_phnum, fp);
431 fputElf32_Half (ehdr->e_shentsize, fp);
432 fputElf32_Half (ehdr->e_shnum, fp);
433 fputElf32_Half (ehdr->e_shstrndx, fp);
436 /*-------------------------------------------------------------------------*/
437 /* fputElf32_Ehdr - writes an Elf32_Shdr struct (section header) to a file */
438 /*-------------------------------------------------------------------------*/
440 fputElf32_Shdr (Elf32_Shdr * shdr, FILE * fp)
442 fputElf32_Word (shdr->sh_name, fp);
443 fputElf32_Word (shdr->sh_type, fp);
444 fputElf32_Word (shdr->sh_flags, fp);
445 fputElf32_Addr (shdr->sh_addr, fp);
446 fputElf32_Off (shdr->sh_offset, fp);
447 fputElf32_Word (shdr->sh_size, fp);
448 fputElf32_Word (shdr->sh_link, fp);
449 fputElf32_Word (shdr->sh_info, fp);
450 fputElf32_Word (shdr->sh_addralign, fp);
451 fputElf32_Word (shdr->sh_entsize, fp);
454 /*-------------------------------------------------------------------------*/
455 /* fputElf32_Ehdr - writes an Elf32_Phdr struct (segment header) to a file */
456 /*-------------------------------------------------------------------------*/
458 fputElf32_Phdr (Elf32_Phdr * phdr, FILE * fp)
460 fputElf32_Word (phdr->p_type, fp);
461 fputElf32_Off (phdr->p_offset, fp);
462 fputElf32_Addr (phdr->p_vaddr, fp);
463 fputElf32_Addr (phdr->p_paddr, fp);
464 fputElf32_Word (phdr->p_filesz, fp);
465 fputElf32_Word (phdr->p_memsz, fp);
466 fputElf32_Word (phdr->p_flags, fp);
467 fputElf32_Word (phdr->p_align, fp);
471 /*--------------------------------------------------------------------------*/
472 /* elfGenerateAbs - generates segments and sections for an absolute area. */
473 /* This is a little more complicated than a relative area since it may */
474 /* contain noncontiguous regions. */
475 /*--------------------------------------------------------------------------*/
477 elfGenerateAbs (struct area *ap, listHeader * segments, listHeader * sections)
494 /* Find the start of a contiguously */
495 /* used region within this area */
496 while (ofs < ap->a_size && !ap->a_used[ofs])
498 if (ofs >= ap->a_size)
501 /* Find the end of the region */
502 addr = ap->a_addr + ofs;
503 while (ofs < ap->a_size && ap->a_used[ofs])
505 size = ap->a_addr + ofs - addr;
507 /* create a segment header for this region if loadable */
508 if (!(ap->a_flag & A_NOLOAD))
510 phdrp = new (sizeof (*phdrp));
511 phdrp->p_type = PT_LOAD;
512 phdrp->p_offset = ftell (ofp);
513 phdrp->p_vaddr = addr;
514 phdrp->p_paddr = addr;
515 phdrp->p_filesz = size;
516 phdrp->p_memsz = size;
517 phdrp->p_flags = PF_R;
518 if (ap->a_flag & A_CODE)
519 phdrp->p_flags |= PF_X;
521 listAdd (segments, phdrp);
524 /* create a section header for this region */
525 shdrp = new (sizeof (*shdrp));
526 shdrp->sh_name = strtabFindOrAdd (&shstrtab, ap->a_id);
527 shdrp->sh_type = SHT_PROGBITS;
529 if (!(ap->a_flag & A_NOLOAD))
530 shdrp->sh_flags |= SHF_ALLOC;
531 if (ap->a_flag & A_CODE)
532 shdrp->sh_flags |= SHF_EXECINSTR;
533 shdrp->sh_addr = addr;
534 shdrp->sh_offset = ftell (ofp);
535 shdrp->sh_size = size;
538 shdrp->sh_addralign = 0;
539 shdrp->sh_entsize = 0;
540 listAdd (sections, shdrp);
542 res = fwrite (&ap->a_image[addr-ap->a_addr], 1, size, ofp);
547 /*--------------------------------------------------------------------------*/
548 /* elfGenerateRel - generates a segment and section for a relative area. */
549 /*--------------------------------------------------------------------------*/
551 elfGenerateRel (struct area *ap, listHeader * segments, listHeader * sections)
562 /* create a segment header for this area if loadable */
563 if (!(ap->a_flag & A_NOLOAD))
565 phdrp = new (sizeof (*phdrp));
566 phdrp->p_type = PT_LOAD;
567 phdrp->p_offset = ftell (ofp);
568 phdrp->p_vaddr = ap->a_addr;
569 phdrp->p_paddr = ap->a_addr;
570 phdrp->p_filesz = ap->a_size;
571 phdrp->p_memsz = ap->a_size;
572 phdrp->p_flags = PF_R;
573 if (ap->a_flag & A_CODE)
574 phdrp->p_flags |= PF_X;
576 listAdd (segments, phdrp);
579 /* create a section header for this area */
580 shdrp = new (sizeof (*shdrp));
581 shdrp->sh_name = strtabFindOrAdd (&shstrtab, ap->a_id);
582 shdrp->sh_type = SHT_PROGBITS;
584 if (!(ap->a_flag & A_NOLOAD))
585 shdrp->sh_flags |= SHF_ALLOC;
586 if (ap->a_flag & A_CODE)
587 shdrp->sh_flags |= SHF_EXECINSTR;
588 shdrp->sh_addr = ap->a_addr;
589 shdrp->sh_offset = ftell (ofp);
590 shdrp->sh_size = ap->a_size;
593 shdrp->sh_addralign = 0;
594 shdrp->sh_entsize = 0;
595 listAdd (sections, shdrp);
597 res = fwrite (ap->a_image, 1, ap->a_size, ofp);
598 assert(res == ap->a_size);
601 /*--------------------------------------------------------------------------*/
602 /* elfGenerate - generates the complete ELF file */
603 /*--------------------------------------------------------------------------*/
607 listHeader * sections = listNew();
608 listHeader * segments = listNew();
615 Elf32_Word shstrtabName;
617 /* create the null section header for index 0 */
618 shdrp = new (sizeof (*shdrp));
620 shdrp->sh_type = SHT_NULL;
623 shdrp->sh_offset = 0;
627 shdrp->sh_addralign = 0;
628 shdrp->sh_entsize = 0;
629 listAdd (sections, shdrp);
631 /* Initialize the ELF header */
632 for (i=0; i<EI_NIDENT; i++)
634 ehdr.e_ident[EI_MAG0] = ELFMAG0;
635 ehdr.e_ident[EI_MAG1] = ELFMAG1;
636 ehdr.e_ident[EI_MAG2] = ELFMAG2;
637 ehdr.e_ident[EI_MAG3] = ELFMAG3;
638 ehdr.e_ident[EI_CLASS] = ELFCLASS32;
640 ehdr.e_ident[EI_DATA] = ELFDATA2LSB;
642 ehdr.e_ident[EI_DATA] = ELFDATA2MSB;
643 ehdr.e_ident[EI_VERSION] = 1;
644 ehdr.e_type = ET_EXEC;
645 ehdr.e_machine = EM_68HC08; /* FIXME: get rid of hardcoded value - EEP */
646 ehdr.e_phentsize = sizeof (*phdrp);
647 ehdr.e_shentsize = sizeof (*shdrp);
648 ehdr.e_ehsize = sizeof (ehdr);
654 if (execStartMSBfound && execStartLSBfound)
655 ehdr.e_entry = (execStartMSB << 8) + execStartLSB;
657 /* Write out the ELF header as a placeholder; we will update */
658 /* it with the final values when everything is complete */
659 fputElf32_Ehdr (&ehdr, ofp);
661 /* Iterate over the linker areas to generate */
662 /* the ELF sections and segments */
668 if (ap->a_flag & A_ABS)
669 elfGenerateAbs (ap, segments, sections);
671 elfGenerateRel (ap, segments, sections);
676 /* Create the string table section after the other sections */
677 shdrp = new (sizeof (*shdrp));
678 shdrp->sh_name = strtabFindOrAdd (&shstrtab, ".shstrtab");
679 shdrp->sh_type = SHT_STRTAB;
682 shdrp->sh_offset = ftell (ofp);
683 shdrp->sh_size = shstrtab.last->index + strlen (shstrtab.last->string) + 1;
686 shdrp->sh_addralign = 0;
687 shdrp->sh_entsize = 0;
688 listAdd (sections, shdrp);
689 fputElfStrtab (&shstrtab, ofp);
691 /* Find the index of the section string table */
692 /* header and save it in the ELF header */
694 shstrtabName = shdrp->sh_name;
695 lep = sections->first;
699 if (shdrp->sh_name == shstrtabName)
705 /* Write out the segment headers */
706 ehdr.e_phnum = segments->count;
707 ehdr.e_phoff = ftell (ofp);
708 lep = segments->first;
712 fputElf32_Phdr (phdrp, ofp);
716 /* Write out the section headers */
717 ehdr.e_shnum = sections->count;
718 ehdr.e_shoff = ftell (ofp);
719 lep = sections->first;
723 fputElf32_Shdr (shdrp, ofp);
727 /* All the values in the ELF header have now been computed; write */
728 /* over the placeholder header with the final values */
729 fseek (ofp, 0, SEEK_SET);
730 fputElf32_Ehdr (&ehdr, ofp);
731 fseek (ofp, 0, SEEK_END);
734 /*--------------------------------------------------------------------------*/
735 /* elf - incrementally called by the linker core to generate ELF file data. */
736 /* The parameter is nonzero when there is data available and zero when */
737 /* the linker is finished. */
738 /*--------------------------------------------------------------------------*/
744 /* Buffer the data until we have it all */
748 address = rtval[0] + (rtval[1] << 8); /* little endian order */
750 address = rtval[1] + (rtval[0] << 8); /* big endian order */
752 /* If this area doesn't have an image buffer, create one */
755 ap->a_image = new (ap->a_size);
756 if (ap->a_flag & A_ABS)
757 ap->a_used = new (ap->a_size);
760 /* Copy the data into the image buffer */
761 for (i = 2; i < rtcnt ; i++)
765 ap->a_image[address-ap->a_addr] = rtval[i];
767 ap->a_used[address-ap->a_addr] = 1;
769 /* Make note of the reset vector */
770 if (!(ap->a_flag & A_NOLOAD))
772 if (address == 0xfffe)
774 execStartMSB = rtval[i];
775 execStartMSBfound = 1;
777 if (address == 0xffff)
779 execStartLSB = rtval[i];
780 execStartLSBfound = 1;