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 -------------------------------------------------------------------------*/
25 #include <asxxxx_config.h>
29 static int execStartMSB;
30 static int execStartLSB;
31 static char execStartMSBfound;
32 static char execStartLSBfound;
34 typedef TYPE_UDWORD Elf32_Addr;
35 typedef TYPE_WORD Elf32_Half;
36 typedef TYPE_UDWORD Elf32_Off;
37 typedef TYPE_DWORD Elf32_Sword;
38 typedef TYPE_UDWORD Elf32_Word;
70 /* These e_machine values are from "Motorola 8- and 16-bit Embedded */
71 /* Application Binary Interface (M8/16EABI)" version 2.0 */
120 SHF_WRITE = (1 << 0),
121 SHF_ALLOC = (1 << 1),
122 SHF_EXECINSTR = (1 << 2),
140 unsigned char e_ident[EI_NIDENT];
142 Elf32_Half e_machine;
143 Elf32_Word e_version;
149 Elf32_Half e_phentsize;
151 Elf32_Half e_shentsize;
153 Elf32_Half e_shstrndx;
166 Elf32_Word sh_addralign;
167 Elf32_Word sh_entsize;
182 typedef struct strtabString
185 struct strtabString * prev;
186 struct strtabString * next;
192 strtabString * first;
196 static strtabList shstrtab;
199 typedef struct listEntry
202 struct listEntry * prev;
203 struct listEntry * next;
216 listAdd (listHeader * lhp, void * item)
220 lep = new (sizeof (*lep));
222 lep->prev = lhp->last;
224 lep->prev->next = lep;
238 lhp = new (sizeof (*lhp));
246 strtabFind (strtabList * strtab, char * str)
253 if (!strcmp (str, sp->string))
262 /*-------------------------------------------------------------------*/
263 /* strtabFindOrAdd - Finds a string in a string table or adds the */
264 /* string if it does not already exist. Returns the offset of the */
265 /* string in the table. */
266 /*-------------------------------------------------------------------*/
268 strtabFindOrAdd (strtabList * strtab, char * str)
275 if (!strcmp (str, sp->string))
280 sp = new (sizeof(*sp));
282 sp->index = strtab->last->index + 1 + strlen (strtab->last->string);
285 sp->string = new (1+strlen (str));
286 strcpy (sp->string, str);
288 sp->prev = strtab->last;
298 /*-------------------------------------------------------------------*/
299 /* fputElfStrtab - writes a string table to a file */
300 /*-------------------------------------------------------------------*/
302 fputElfStrtab (strtabList *strtab, FILE *fp)
306 fputc (0, fp); /* index 0 must be the null character */
311 fputs (sp->string, fp);
317 /*-------------------------------------------------------------------*/
318 /* fputElf32_Word - writes an Elf32_Word value to a file */
319 /*-------------------------------------------------------------------*/
321 fputElf32_Word (Elf32_Word x, FILE *fp)
325 fputc (x & 0xff, fp);
326 fputc ((x >> 8) & 0xff, fp);
327 fputc ((x >> 16) & 0xff, fp);
328 fputc ((x >> 24) & 0xff, fp);
332 fputc ((x >> 24) & 0xff, fp);
333 fputc ((x >> 16) & 0xff, fp);
334 fputc ((x >> 8) & 0xff, fp);
335 fputc (x & 0xff, fp);
339 /*-------------------------------------------------------------------*/
340 /* fputElf32_Off - writes an Elf32_Off value to a file */
341 /*-------------------------------------------------------------------*/
343 fputElf32_Off (Elf32_Off x, FILE *fp)
347 fputc (x & 0xff, fp);
348 fputc ((x >> 8) & 0xff, fp);
349 fputc ((x >> 16) & 0xff, fp);
350 fputc ((x >> 24) & 0xff, fp);
354 fputc ((x >> 24) & 0xff, fp);
355 fputc ((x >> 16) & 0xff, fp);
356 fputc ((x >> 8) & 0xff, fp);
357 fputc (x & 0xff, fp);
361 /*-------------------------------------------------------------------*/
362 /* fputElf32_Addr - writes an Elf32_Addr value to a file */
363 /*-------------------------------------------------------------------*/
365 fputElf32_Addr (Elf32_Addr x, FILE *fp)
369 fputc (x & 0xff, fp);
370 fputc ((x >> 8) & 0xff, fp);
371 fputc ((x >> 16) & 0xff, fp);
372 fputc ((x >> 24) & 0xff, fp);
376 fputc ((x >> 24) & 0xff, fp);
377 fputc ((x >> 16) & 0xff, fp);
378 fputc ((x >> 8) & 0xff, fp);
379 fputc (x & 0xff, fp);
383 /*-------------------------------------------------------------------*/
384 /* fputElf32_Half - writes an Elf32_Half value to a file */
385 /*-------------------------------------------------------------------*/
387 fputElf32_Half (Elf32_Half x, FILE *fp)
391 fputc (x & 0xff, fp);
392 fputc ((x >> 8) & 0xff, fp);
396 fputc ((x >> 8) & 0xff, fp);
397 fputc (x & 0xff, fp);
401 /*------------------------------------------------------------------------*/
402 /* fputElf32_Ehdr - writes an Elf32_Ehdr struct (ELF header) to a file */
403 /*------------------------------------------------------------------------*/
405 fputElf32_Ehdr (Elf32_Ehdr * ehdr, FILE * fp)
409 for (i=0; i<EI_NIDENT; i++)
410 fputc (ehdr->e_ident[i], fp);
412 fputElf32_Half (ehdr->e_type, fp);
413 fputElf32_Half (ehdr->e_machine, fp);
414 fputElf32_Word (ehdr->e_version, fp);
415 fputElf32_Addr (ehdr->e_entry, fp);
416 fputElf32_Off (ehdr->e_phoff, fp);
417 fputElf32_Off (ehdr->e_shoff, fp);
418 fputElf32_Word (ehdr->e_flags, fp);
419 fputElf32_Half (ehdr->e_ehsize, fp);
420 fputElf32_Half (ehdr->e_phentsize, fp);
421 fputElf32_Half (ehdr->e_phnum, fp);
422 fputElf32_Half (ehdr->e_shentsize, fp);
423 fputElf32_Half (ehdr->e_shnum, fp);
424 fputElf32_Half (ehdr->e_shstrndx, fp);
427 /*-------------------------------------------------------------------------*/
428 /* fputElf32_Ehdr - writes an Elf32_Shdr struct (section header) to a file */
429 /*-------------------------------------------------------------------------*/
431 fputElf32_Shdr (Elf32_Shdr * shdr, FILE * fp)
433 fputElf32_Word (shdr->sh_name, fp);
434 fputElf32_Word (shdr->sh_type, fp);
435 fputElf32_Word (shdr->sh_flags, fp);
436 fputElf32_Addr (shdr->sh_addr, fp);
437 fputElf32_Off (shdr->sh_offset, fp);
438 fputElf32_Word (shdr->sh_size, fp);
439 fputElf32_Word (shdr->sh_link, fp);
440 fputElf32_Word (shdr->sh_info, fp);
441 fputElf32_Word (shdr->sh_addralign, fp);
442 fputElf32_Word (shdr->sh_entsize, fp);
445 /*-------------------------------------------------------------------------*/
446 /* fputElf32_Ehdr - writes an Elf32_Phdr struct (segment header) to a file */
447 /*-------------------------------------------------------------------------*/
449 fputElf32_Phdr (Elf32_Phdr * phdr, FILE * fp)
451 fputElf32_Word (phdr->p_type, fp);
452 fputElf32_Off (phdr->p_offset, fp);
453 fputElf32_Addr (phdr->p_vaddr, fp);
454 fputElf32_Addr (phdr->p_paddr, fp);
455 fputElf32_Word (phdr->p_filesz, fp);
456 fputElf32_Word (phdr->p_memsz, fp);
457 fputElf32_Word (phdr->p_flags, fp);
458 fputElf32_Word (phdr->p_align, fp);
462 /*--------------------------------------------------------------------------*/
463 /* elfGenerateAbs - generates segments and sections for an absolute area. */
464 /* This is a little more complicated than a relative area since it may */
465 /* contain noncontiguous regions. */
466 /*--------------------------------------------------------------------------*/
468 elfGenerateAbs (struct area *ap, listHeader * segments, listHeader * sections)
484 /* Find the start of a contiguously */
485 /* used region within this area */
486 while (ofs < ap->a_size && !ap->a_used[ofs])
488 if (ofs >= ap->a_size)
491 /* Find the end of the region */
492 addr = ap->a_addr + ofs;
493 while (ofs < ap->a_size && ap->a_used[ofs])
495 size = ap->a_addr + ofs - addr;
497 /* create a segment header for this region if loadable */
498 if (!(ap->a_flag & A_NOLOAD))
500 phdrp = new (sizeof (*phdrp));
501 phdrp->p_type = PT_LOAD;
502 phdrp->p_offset = ftell (ofp);
503 phdrp->p_vaddr = addr;
504 phdrp->p_paddr = addr;
505 phdrp->p_filesz = size;
506 phdrp->p_memsz = size;
507 phdrp->p_flags = PF_R;
508 if (ap->a_flag & A_CODE)
509 phdrp->p_flags |= PF_X;
511 listAdd (segments, phdrp);
514 /* create a section header for this region */
515 shdrp = new (sizeof (*shdrp));
516 shdrp->sh_name = strtabFindOrAdd (&shstrtab, ap->a_id);
517 shdrp->sh_type = SHT_PROGBITS;
519 if (!(ap->a_flag & A_NOLOAD))
520 shdrp->sh_flags |= SHF_ALLOC;
521 if (ap->a_flag & A_CODE)
522 shdrp->sh_flags |= SHF_EXECINSTR;
523 shdrp->sh_addr = addr;
524 shdrp->sh_offset = ftell (ofp);
525 shdrp->sh_size = size;
528 shdrp->sh_addralign = 0;
529 shdrp->sh_entsize = 0;
530 listAdd (sections, shdrp);
532 fwrite (&ap->a_image[addr-ap->a_addr], 1, size, ofp);
536 /*--------------------------------------------------------------------------*/
537 /* elfGenerateRel - generates a segment and section for a relative area. */
538 /*--------------------------------------------------------------------------*/
540 elfGenerateRel (struct area *ap, listHeader * segments, listHeader * sections)
550 /* create a segment header for this area if loadable */
551 if (!(ap->a_flag & A_NOLOAD))
553 phdrp = new (sizeof (*phdrp));
554 phdrp->p_type = PT_LOAD;
555 phdrp->p_offset = ftell (ofp);
556 phdrp->p_vaddr = ap->a_addr;
557 phdrp->p_paddr = ap->a_addr;
558 phdrp->p_filesz = ap->a_size;
559 phdrp->p_memsz = ap->a_size;
560 phdrp->p_flags = PF_R;
561 if (ap->a_flag & A_CODE)
562 phdrp->p_flags |= PF_X;
564 listAdd (segments, phdrp);
567 /* create a section header for this area */
568 shdrp = new (sizeof (*shdrp));
569 shdrp->sh_name = strtabFindOrAdd (&shstrtab, ap->a_id);
570 shdrp->sh_type = SHT_PROGBITS;
572 if (!(ap->a_flag & A_NOLOAD))
573 shdrp->sh_flags |= SHF_ALLOC;
574 if (ap->a_flag & A_CODE)
575 shdrp->sh_flags |= SHF_EXECINSTR;
576 shdrp->sh_addr = ap->a_addr;
577 shdrp->sh_offset = ftell (ofp);
578 shdrp->sh_size = ap->a_size;
581 shdrp->sh_addralign = 0;
582 shdrp->sh_entsize = 0;
583 listAdd (sections, shdrp);
585 fwrite (ap->a_image, 1, ap->a_size, ofp);
588 /*--------------------------------------------------------------------------*/
589 /* elfGenerate - generates the complete ELF file */
590 /*--------------------------------------------------------------------------*/
594 listHeader * sections = listNew();
595 listHeader * segments = listNew();
602 Elf32_Word shstrtabName;
604 /* create the null section header for index 0 */
605 shdrp = new (sizeof (*shdrp));
607 shdrp->sh_type = SHT_NULL;
610 shdrp->sh_offset = 0;
614 shdrp->sh_addralign = 0;
615 shdrp->sh_entsize = 0;
616 listAdd (sections, shdrp);
618 /* Initialize the ELF header */
619 for (i=0; i<EI_NIDENT; i++)
621 ehdr.e_ident[EI_MAG0] = ELFMAG0;
622 ehdr.e_ident[EI_MAG1] = ELFMAG1;
623 ehdr.e_ident[EI_MAG2] = ELFMAG2;
624 ehdr.e_ident[EI_MAG3] = ELFMAG3;
625 ehdr.e_ident[EI_CLASS] = ELFCLASS32;
627 ehdr.e_ident[EI_DATA] = ELFDATA2LSB;
629 ehdr.e_ident[EI_DATA] = ELFDATA2MSB;
630 ehdr.e_ident[EI_VERSION] = 1;
631 ehdr.e_type = ET_EXEC;
632 ehdr.e_machine = EM_68HC08; /* FIXME: get rid of hardcoded value - EEP */
633 ehdr.e_phentsize = sizeof (*phdrp);
634 ehdr.e_shentsize = sizeof (*shdrp);
635 ehdr.e_ehsize = sizeof (ehdr);
641 if (execStartMSBfound && execStartLSBfound)
642 ehdr.e_entry = (execStartMSB << 8) + execStartLSB;
644 /* Write out the ELF header as a placeholder; we will update */
645 /* it with the final values when everything is complete */
646 fputElf32_Ehdr (&ehdr, ofp);
648 /* Iterate over the linker areas to generate */
649 /* the ELF sections and segments */
655 if (ap->a_flag & A_ABS)
656 elfGenerateAbs (ap, segments, sections);
658 elfGenerateRel (ap, segments, sections);
663 /* Create the string table section after the other sections */
664 shdrp = new (sizeof (*shdrp));
665 shdrp->sh_name = strtabFindOrAdd (&shstrtab, ".shstrtab");
666 shdrp->sh_type = SHT_STRTAB;
669 shdrp->sh_offset = ftell (ofp);
670 shdrp->sh_size = shstrtab.last->index + strlen (shstrtab.last->string) + 1;
673 shdrp->sh_addralign = 0;
674 shdrp->sh_entsize = 0;
675 listAdd (sections, shdrp);
676 fputElfStrtab (&shstrtab, ofp);
678 /* Find the index of the section string table */
679 /* header and save it in the ELF header */
681 shstrtabName = shdrp->sh_name;
682 lep = sections->first;
686 if (shdrp->sh_name == shstrtabName)
692 /* Write out the segment headers */
693 ehdr.e_phnum = segments->count;
694 ehdr.e_phoff = ftell (ofp);
695 lep = segments->first;
699 fputElf32_Phdr (phdrp, ofp);
703 /* Write out the section headers */
704 ehdr.e_shnum = sections->count;
705 ehdr.e_shoff = ftell (ofp);
706 lep = sections->first;
710 fputElf32_Shdr (shdrp, ofp);
714 /* All the values in the ELF header have now been computed; write */
715 /* over the placeholder header with the final values */
716 fseek (ofp, 0, SEEK_SET);
717 fputElf32_Ehdr (&ehdr, ofp);
718 fseek (ofp, 0, SEEK_END);
721 /*--------------------------------------------------------------------------*/
722 /* elf - incrementally called by the linker core to generate ELF file data. */
723 /* The parameter is nonzero when there is data available and zero when */
724 /* the linker is finished. */
725 /*--------------------------------------------------------------------------*/
731 /* Buffer the data until we have it all */
735 address = rtval[0] + (rtval[1] << 8); /* little endian order */
737 address = rtval[1] + (rtval[0] << 8); /* big endian order */
739 /* If this area doesn't have an image buffer, create one */
742 ap->a_image = new (ap->a_size);
743 if (ap->a_flag & A_ABS)
744 ap->a_used = new (ap->a_size);
747 /* Copy the data into the image buffer */
748 for (i = 2; i < rtcnt ; i++)
752 ap->a_image[address-ap->a_addr] = rtval[i];
754 ap->a_used[address-ap->a_addr] = 1;
756 /* Make note of the reset vector */
757 if (!(ap->a_flag & A_NOLOAD))
759 if (address == 0xfffe)
761 execStartMSB = rtval[i];
762 execStartMSBfound = 1;
764 if (address == 0xffff)
766 execStartLSB = rtval[i];
767 execStartLSBfound = 1;