1 /* lkelf.c - Create an executable ELF/DWARF file
3 Copyright (C) 2004 Erik Petrich, epetrich at users dot sourceforge dot net
4 Copyright (C) 2015 Peter Dons Tychsen at pdt dot dontech dot dk
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 3, 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, see <http://www.gnu.org/licenses/>. */
23 #include <asxxxx_config.h>
27 static int execStartMSB
;
28 static int execStartLSB
;
29 static char execStartMSBfound
;
30 static char execStartLSBfound
;
32 typedef TYPE_UDWORD Elf32_Addr
;
33 typedef TYPE_WORD Elf32_Half
;
34 typedef TYPE_UDWORD Elf32_Off
;
35 typedef TYPE_DWORD Elf32_Sword
;
36 typedef TYPE_UDWORD Elf32_Word
;
68 /* These e_machine values are from "Motorola 8- and 16-bit Embedded */
69 /* Application Binary Interface (M8/16EABI)" version 2.0 */
119 SHF_WRITE
= (1 << 0),
120 SHF_ALLOC
= (1 << 1),
121 SHF_EXECINSTR
= (1 << 2),
130 #define ELF32_ST_INFO(b,t) (((b)<<4)+((t)&0xf))
147 unsigned char e_ident
[EI_NIDENT
];
149 Elf32_Half e_machine
;
150 Elf32_Word e_version
;
156 Elf32_Half e_phentsize
;
158 Elf32_Half e_shentsize
;
160 Elf32_Half e_shstrndx
;
173 Elf32_Word sh_addralign
;
174 Elf32_Word sh_entsize
;
194 unsigned char st_info
;
195 unsigned char st_other
;
199 typedef struct strtabString
202 struct strtabString
* prev
;
203 struct strtabString
* next
;
209 strtabString
* first
;
213 static strtabList shstrtab
;
214 static strtabList strtab
;
217 typedef struct listEntry
220 struct listEntry
* prev
;
221 struct listEntry
* next
;
234 listAdd (listHeader
* lhp
, void * item
)
238 lep
= (listEntry
*)new (sizeof (*lep
));
240 lep
->prev
= lhp
->last
;
242 lep
->prev
->next
= lep
;
256 lhp
= (listHeader
*)new (sizeof (*lhp
));
261 /*---------------------------------------------------------------------*/
262 /* strtabFind - Find section header index in a list of section headers */
263 /* Returns the offset of the section */
264 /*---------------------------------------------------------------------*/
266 strtabFindShndx (strtabList
* strtab
, char * str
)
269 Elf32_Half shndx
= 0;
274 if (!strcmp (str
, sp
->string
))
283 /*-------------------------------------------------------------------*/
284 /* strtabFindOrAdd - Finds a string in a string table or adds the */
285 /* string if it does not already exist. Returns the offset of the */
286 /* string in the table. */
287 /*-------------------------------------------------------------------*/
289 strtabFindOrAdd (strtabList
* strtab
, char * str
)
296 if (!strcmp (str
, sp
->string
))
301 sp
= (strtabString
*)new (sizeof(*sp
));
303 sp
->index
= strtab
->last
->index
+ 1 + strlen (strtab
->last
->string
);
306 sp
->string
= new (1+strlen (str
));
307 strcpy (sp
->string
, str
);
309 sp
->prev
= strtab
->last
;
319 /*-------------------------------------------------------------------*/
320 /* fputElfStrtab - writes a string table to a file */
321 /*-------------------------------------------------------------------*/
323 fputElfStrtab (strtabList
*strtab
, FILE *fp
)
327 fputc (0, fp
); /* index 0 must be the null character */
332 fputs (sp
->string
, fp
);
338 /*-------------------------------------------------------------------*/
339 /* fputElf32_Word - writes an Elf32_Word value to a file */
340 /*-------------------------------------------------------------------*/
342 fputElf32_Word (Elf32_Word x
, FILE *fp
)
346 fputc (x
& 0xff, fp
);
347 fputc ((x
>> 8) & 0xff, fp
);
348 fputc ((x
>> 16) & 0xff, fp
);
349 fputc ((x
>> 24) & 0xff, fp
);
353 fputc ((x
>> 24) & 0xff, fp
);
354 fputc ((x
>> 16) & 0xff, fp
);
355 fputc ((x
>> 8) & 0xff, fp
);
356 fputc (x
& 0xff, fp
);
360 /*-------------------------------------------------------------------*/
361 /* fputElf32_Off - writes an Elf32_Off value to a file */
362 /*-------------------------------------------------------------------*/
364 fputElf32_Off (Elf32_Off x
, FILE *fp
)
368 fputc (x
& 0xff, fp
);
369 fputc ((x
>> 8) & 0xff, fp
);
370 fputc ((x
>> 16) & 0xff, fp
);
371 fputc ((x
>> 24) & 0xff, fp
);
375 fputc ((x
>> 24) & 0xff, fp
);
376 fputc ((x
>> 16) & 0xff, fp
);
377 fputc ((x
>> 8) & 0xff, fp
);
378 fputc (x
& 0xff, fp
);
382 /*-------------------------------------------------------------------*/
383 /* fputElf32_Addr - writes an Elf32_Addr value to a file */
384 /*-------------------------------------------------------------------*/
386 fputElf32_Addr (Elf32_Addr x
, FILE *fp
)
390 fputc (x
& 0xff, fp
);
391 fputc ((x
>> 8) & 0xff, fp
);
392 fputc ((x
>> 16) & 0xff, fp
);
393 fputc ((x
>> 24) & 0xff, fp
);
397 fputc ((x
>> 24) & 0xff, fp
);
398 fputc ((x
>> 16) & 0xff, fp
);
399 fputc ((x
>> 8) & 0xff, fp
);
400 fputc (x
& 0xff, fp
);
404 /*-------------------------------------------------------------------*/
405 /* fputElf32_Half - writes an Elf32_Half value to a file */
406 /*-------------------------------------------------------------------*/
408 fputElf32_Half (Elf32_Half x
, FILE *fp
)
412 fputc (x
& 0xff, fp
);
413 fputc ((x
>> 8) & 0xff, fp
);
417 fputc ((x
>> 8) & 0xff, fp
);
418 fputc (x
& 0xff, fp
);
422 /*------------------------------------------------------------------------*/
423 /* fputElf32_Ehdr - writes an Elf32_Ehdr struct (ELF header) to a file */
424 /*------------------------------------------------------------------------*/
426 fputElf32_Ehdr (Elf32_Ehdr
* ehdr
, FILE * fp
)
430 for (i
=0; i
<EI_NIDENT
; i
++)
431 fputc (ehdr
->e_ident
[i
], fp
);
433 fputElf32_Half (ehdr
->e_type
, fp
);
434 fputElf32_Half (ehdr
->e_machine
, fp
);
435 fputElf32_Word (ehdr
->e_version
, fp
);
436 fputElf32_Addr (ehdr
->e_entry
, fp
);
437 fputElf32_Off (ehdr
->e_phoff
, fp
);
438 fputElf32_Off (ehdr
->e_shoff
, fp
);
439 fputElf32_Word (ehdr
->e_flags
, fp
);
440 fputElf32_Half (ehdr
->e_ehsize
, fp
);
441 fputElf32_Half (ehdr
->e_phentsize
, fp
);
442 fputElf32_Half (ehdr
->e_phnum
, fp
);
443 fputElf32_Half (ehdr
->e_shentsize
, fp
);
444 fputElf32_Half (ehdr
->e_shnum
, fp
);
445 fputElf32_Half (ehdr
->e_shstrndx
, fp
);
448 /*-------------------------------------------------------------------------*/
449 /* fputElf32_Ehdr - writes an Elf32_Shdr struct (section header) to a file */
450 /*-------------------------------------------------------------------------*/
452 fputElf32_Shdr (Elf32_Shdr
* shdr
, FILE * fp
)
454 fputElf32_Word (shdr
->sh_name
, fp
);
455 fputElf32_Word (shdr
->sh_type
, fp
);
456 fputElf32_Word (shdr
->sh_flags
, fp
);
457 fputElf32_Addr (shdr
->sh_addr
, fp
);
458 fputElf32_Off (shdr
->sh_offset
, fp
);
459 fputElf32_Word (shdr
->sh_size
, fp
);
460 fputElf32_Word (shdr
->sh_link
, fp
);
461 fputElf32_Word (shdr
->sh_info
, fp
);
462 fputElf32_Word (shdr
->sh_addralign
, fp
);
463 fputElf32_Word (shdr
->sh_entsize
, fp
);
466 /*-------------------------------------------------------------------------*/
467 /* fputElf32_Ehdr - writes an Elf32_Phdr struct (segment header) to a file */
468 /*-------------------------------------------------------------------------*/
470 fputElf32_Phdr (Elf32_Phdr
* phdr
, FILE * fp
)
472 fputElf32_Word (phdr
->p_type
, fp
);
473 fputElf32_Off (phdr
->p_offset
, fp
);
474 fputElf32_Addr (phdr
->p_vaddr
, fp
);
475 fputElf32_Addr (phdr
->p_paddr
, fp
);
476 fputElf32_Word (phdr
->p_filesz
, fp
);
477 fputElf32_Word (phdr
->p_memsz
, fp
);
478 fputElf32_Word (phdr
->p_flags
, fp
);
479 fputElf32_Word (phdr
->p_align
, fp
);
482 /*-------------------------------------------------------------------------*/
483 /* fputElf32_Sym - writes an Elf32_Sym struct (symbol) to a file */
484 /*-------------------------------------------------------------------------*/
486 fputElf32_Sym (Elf32_Sym
* symhdr
, FILE * fp
)
488 fputElf32_Word (symhdr
->st_name
, fp
);
489 fputElf32_Addr (symhdr
->st_value
, fp
);
490 fputElf32_Word (symhdr
->st_size
, fp
);
491 fputc (symhdr
->st_info
, fp
);
492 fputc (symhdr
->st_other
, fp
);
493 fputElf32_Half (symhdr
->st_shndx
, fp
);
510 /*--------------------------------------------------------------------------*/
511 /* elfGenerateSyms - generates symbol headers for a list of symbols */
512 /*--------------------------------------------------------------------------*/
514 elfGenerateSyms(struct head
*hp
)
521 symhdr
= (Elf32_Sym
*)new (sizeof (*symhdr
));
522 fputElf32_Sym (symhdr
, ofp
);
524 /* Add all modules */
527 /* Add all symbols */
528 for(i
=0;i
<hp
->h_nsym
;i
++)
533 symhdr
= (Elf32_Sym
*)new (sizeof (*symhdr
));
534 symhdr
->st_name
= strtabFindOrAdd(&strtab
,sym
->s_id
);
535 symhdr
->st_value
= sym
->s_addr
+ sym
->s_axp
->a_addr
;
536 symhdr
->st_shndx
= strtabFindShndx(&shstrtab
,sym
->s_axp
->a_bap
->a_id
);
537 symhdr
->st_info
= ELF32_ST_INFO(STB_GLOBAL
,STT_FUNC
);
538 if(!symhdr
->st_shndx
)
540 symhdr
->st_shndx
= SHN_ABS
;
543 fputElf32_Sym (symhdr
, ofp
);
550 /*--------------------------------------------------------------------------*/
551 /* elfGenerateAbs - generates segments and sections for an absolute area. */
552 /* This is a little more complicated than a relative area since it may */
553 /* contain noncontiguous regions. */
554 /*--------------------------------------------------------------------------*/
556 elfGenerateAbs (struct area
*ap
, listHeader
* segments
, listHeader
* sections
)
572 /* Find the start of a contiguously */
573 /* used region within this area */
574 while (ofs
< ap
->a_imagesize
&& !ap
->a_used
[ofs
])
576 if (ofs
>= ap
->a_imagesize
)
579 /* Find the end of the region */
580 addr
= ap
->a_addr
+ ofs
;
581 while (ofs
< ap
->a_imagesize
&& ap
->a_used
[ofs
])
583 size
= ap
->a_addr
+ ofs
- addr
;
585 /* create a segment header for this region if loadable */
586 if (!(ap
->a_flag
& A_NOLOAD
))
588 phdrp
= (Elf32_Phdr
*)new (sizeof (*phdrp
));
589 phdrp
->p_type
= PT_LOAD
;
590 phdrp
->p_offset
= ftell (ofp
);
591 phdrp
->p_vaddr
= addr
;
592 phdrp
->p_paddr
= addr
;
593 phdrp
->p_filesz
= size
;
594 phdrp
->p_memsz
= size
;
595 phdrp
->p_flags
= PF_R
;
596 if (ap
->a_flag
& A_CODE
)
597 phdrp
->p_flags
|= PF_X
;
599 listAdd (segments
, phdrp
);
602 /* create a section header for this region */
603 shdrp
= (Elf32_Shdr
*)new (sizeof (*shdrp
));
604 shdrp
->sh_name
= strtabFindOrAdd (&shstrtab
, ap
->a_id
);
605 shdrp
->sh_type
= SHT_PROGBITS
;
607 if (!(ap
->a_flag
& A_NOLOAD
))
608 shdrp
->sh_flags
|= SHF_ALLOC
;
609 if (ap
->a_flag
& A_CODE
)
610 shdrp
->sh_flags
|= SHF_EXECINSTR
;
611 shdrp
->sh_addr
= addr
;
612 shdrp
->sh_offset
= ftell (ofp
);
613 shdrp
->sh_size
= size
;
616 shdrp
->sh_addralign
= 0;
617 shdrp
->sh_entsize
= 0;
618 listAdd (sections
, shdrp
);
620 fwrite (&ap
->a_image
[addr
-ap
->a_addr
], 1, size
, ofp
);
624 /*--------------------------------------------------------------------------*/
625 /* elfGenerateRel - generates a segment and section for a relative area. */
626 /*--------------------------------------------------------------------------*/
628 elfGenerateRel (struct area
*ap
, listHeader
* segments
, listHeader
* sections
)
638 /* create a segment header for this area if loadable */
639 if (!(ap
->a_flag
& A_NOLOAD
))
641 phdrp
= (Elf32_Phdr
*)new (sizeof (*phdrp
));
642 phdrp
->p_type
= PT_LOAD
;
643 phdrp
->p_offset
= ftell (ofp
);
644 phdrp
->p_vaddr
= ap
->a_addr
;
645 phdrp
->p_paddr
= ap
->a_addr
;
646 phdrp
->p_filesz
= ap
->a_size
;
647 phdrp
->p_memsz
= ap
->a_size
;
648 phdrp
->p_flags
= PF_R
;
649 if (ap
->a_flag
& A_CODE
)
650 phdrp
->p_flags
|= PF_X
;
652 listAdd (segments
, phdrp
);
655 /* create a section header for this area */
656 shdrp
= (Elf32_Shdr
*)new (sizeof (*shdrp
));
657 shdrp
->sh_name
= strtabFindOrAdd (&shstrtab
, ap
->a_id
);
658 shdrp
->sh_type
= SHT_PROGBITS
;
660 if (!(ap
->a_flag
& A_NOLOAD
))
661 shdrp
->sh_flags
|= SHF_ALLOC
;
662 if (ap
->a_flag
& A_CODE
)
663 shdrp
->sh_flags
|= SHF_EXECINSTR
;
664 shdrp
->sh_addr
= ap
->a_addr
;
665 shdrp
->sh_offset
= ftell (ofp
);
666 shdrp
->sh_size
= ap
->a_size
;
669 shdrp
->sh_addralign
= 0;
670 shdrp
->sh_entsize
= 0;
671 listAdd (sections
, shdrp
);
673 fwrite (ap
->a_image
, 1, ap
->a_size
, ofp
);
676 /*--------------------------------------------------------------------------*/
677 /* elfGenerate - generates the complete ELF file */
678 /*--------------------------------------------------------------------------*/
682 listHeader
* sections
= listNew();
683 listHeader
* segments
= listNew();
690 Elf32_Word shstrtabName
;
692 /* create the null section header for index 0 */
693 shdrp
= (Elf32_Shdr
*)new (sizeof (*shdrp
));
695 shdrp
->sh_type
= SHT_NULL
;
698 shdrp
->sh_offset
= 0;
702 shdrp
->sh_addralign
= 0;
703 shdrp
->sh_entsize
= 0;
704 listAdd (sections
, shdrp
);
706 /* Initialize the ELF header */
707 for (i
=0; i
<EI_NIDENT
; i
++)
709 ehdr
.e_ident
[EI_MAG0
] = ELFMAG0
;
710 ehdr
.e_ident
[EI_MAG1
] = ELFMAG1
;
711 ehdr
.e_ident
[EI_MAG2
] = ELFMAG2
;
712 ehdr
.e_ident
[EI_MAG3
] = ELFMAG3
;
713 ehdr
.e_ident
[EI_CLASS
] = ELFCLASS32
;
715 ehdr
.e_ident
[EI_DATA
] = ELFDATA2LSB
;
717 ehdr
.e_ident
[EI_DATA
] = ELFDATA2MSB
;
718 ehdr
.e_ident
[EI_VERSION
] = 1;
719 ehdr
.e_ident
[EI_PAD
] = 8;
720 ehdr
.e_type
= ET_EXEC
;
721 ehdr
.e_machine
= TARGET_IS_STM8
? EM_STM8
: EM_68HC08
; /* FIXME: get rid of hardcoded value - EEP */
722 ehdr
.e_phentsize
= sizeof (*phdrp
);
723 ehdr
.e_shentsize
= sizeof (*shdrp
);
724 ehdr
.e_ehsize
= sizeof (ehdr
);
730 if (execStartMSBfound
&& execStartLSBfound
)
731 ehdr
.e_entry
= (execStartMSB
<< 8) + execStartLSB
;
734 struct sym
*entryp_sym
;
735 entryp_sym
= lkpsym("s_GSINIT",0);
738 ehdr
.e_entry
= entryp_sym
->s_addr
+ entryp_sym
->s_axp
->a_addr
;
742 /* Write out the ELF header as a placeholder; we will update */
743 /* it with the final values when everything is complete */
744 fputElf32_Ehdr (&ehdr
, ofp
);
746 /* Iterate over the linker areas to generate */
747 /* the ELF sections and segments */
753 if (ap
->a_flag
& A3_ABS
)
754 elfGenerateAbs (ap
, segments
, sections
);
756 elfGenerateRel (ap
, segments
, sections
);
761 /* Create symbol table section */
762 shdrp
= (Elf32_Shdr
*)new (sizeof (*shdrp
));
763 shdrp
->sh_name
= strtabFindOrAdd (&shstrtab
, ".symtab");
764 shdrp
->sh_type
= SHT_SYMTAB
;
767 shdrp
->sh_offset
= ftell (ofp
);
768 shdrp
->sh_link
= sections
->count
+1;
770 shdrp
->sh_addralign
= 0;
771 shdrp
->sh_entsize
= sizeof(Elf32_Sym
);
772 lep
= sections
->first
;
773 /* Generate symbols */
774 elfGenerateSyms(headp
);
775 shdrp
->sh_size
= ftell(ofp
) - shdrp
->sh_offset
;
776 listAdd (sections
, shdrp
);
778 /* Create string table section */
779 shdrp
= (Elf32_Shdr
*)new (sizeof (*shdrp
));
780 shdrp
->sh_name
= strtabFindOrAdd (&shstrtab
, ".strtab");
781 shdrp
->sh_type
= SHT_STRTAB
;
784 shdrp
->sh_offset
= ftell (ofp
);
785 shdrp
->sh_size
= strtab
.last
? (strtab
.last
->index
+ strlen (strtab
.last
->string
) + 1) : 0;
788 shdrp
->sh_addralign
= 0;
789 shdrp
->sh_entsize
= 0;
790 listAdd (sections
, shdrp
);
791 fputElfStrtab (&strtab
, ofp
);
793 /* Create the section header string table section after the other sections */
794 shdrp
= (Elf32_Shdr
*)new (sizeof (*shdrp
));
795 shdrp
->sh_name
= strtabFindOrAdd (&shstrtab
, ".shstrtab");
796 shdrp
->sh_type
= SHT_STRTAB
;
799 shdrp
->sh_offset
= ftell (ofp
);
800 shdrp
->sh_size
= shstrtab
.last
->index
+ strlen (shstrtab
.last
->string
) + 1;
803 shdrp
->sh_addralign
= 0;
804 shdrp
->sh_entsize
= 0;
805 listAdd (sections
, shdrp
);
806 fputElfStrtab (&shstrtab
, ofp
);
808 /* Find the index of the section string table */
809 /* header and save it in the ELF header */
811 shstrtabName
= shdrp
->sh_name
;
812 lep
= sections
->first
;
816 if (shdrp
->sh_name
== shstrtabName
)
822 /* Write out the segment headers */
823 ehdr
.e_phnum
= segments
->count
;
824 ehdr
.e_phoff
= ftell (ofp
);
825 lep
= segments
->first
;
829 fputElf32_Phdr (phdrp
, ofp
);
833 /* Write out the section headers */
834 ehdr
.e_shnum
= sections
->count
;
835 ehdr
.e_shoff
= ftell (ofp
);
836 lep
= sections
->first
;
840 fputElf32_Shdr (shdrp
, ofp
);
844 /* All the values in the ELF header have now been computed; write */
845 /* over the placeholder header with the final values */
846 fseek (ofp
, 0, SEEK_SET
);
847 fputElf32_Ehdr (&ehdr
, ofp
);
848 fseek (ofp
, 0, SEEK_END
);
851 /*--------------------------------------------------------------------------*/
852 /* elf - incrementally called by the linker core to generate ELF file data. */
853 /* The parameter is nonzero when there is data available and zero when */
854 /* the linker is finished. */
855 /*--------------------------------------------------------------------------*/
861 /* Buffer the data until we have it all */
864 /* 3 bytes address */
868 address
= rtval
[0] + (rtval
[1] << 8) + (rtval
[2] << 16); /* little endian order */
870 address
= rtval
[2] + (rtval
[1] << 8) + (rtval
[0] << 16); /* big endian order */
872 /* 2 bytes address */
876 address
= rtval
[0] + (rtval
[1] << 8); /* little endian order */
878 address
= rtval
[1] + (rtval
[0] << 8); /* big endian order */
881 /* If this area doesn't have an image buffer, create one */
884 if (ap
->a_flag
& A3_ABS
)
885 ap
->a_imagesize
= ap
->a_addr
+ ap
->a_size
;
887 ap
->a_imagesize
= ap
->a_size
;
888 ap
->a_image
= new (ap
->a_imagesize
);
889 if (ap
->a_flag
& A3_ABS
)
890 ap
->a_used
= new (ap
->a_imagesize
);
893 /* Copy the data into the image buffer */
894 for (i
= a_bytes
; i
< rtcnt
; i
++)
898 if (address
-ap
->a_addr
>= ap
->a_imagesize
)
902 if (ap
->a_flag
& A3_ABS
)
904 newsize
= ap
->a_imagesize
;
905 while (address
-ap
->a_addr
>= newsize
)
906 newsize
= (newsize
& ~4095)+4096;
907 ap
->a_image
= (char *) realloc (ap
->a_image
, newsize
);
908 ap
->a_used
= (char *) realloc (ap
->a_used
, newsize
);
909 if (!ap
->a_image
|| !ap
->a_used
)
911 fprintf (stderr
, "Out of space!\n");
914 memset (ap
->a_image
+ap
->a_imagesize
, 0, newsize
-ap
->a_imagesize
);
915 memset (ap
->a_used
+ap
->a_imagesize
, 0, newsize
-ap
->a_imagesize
);
916 ap
->a_imagesize
= newsize
;
920 fprintf (stderr
, "Unexpected area %s overflow. Address = 0x%x but allocated range is 0x%x - 0x%x\n",
921 ap
->a_id
, address
, ap
->a_addr
, ap
->a_addr
+ap
->a_imagesize
-1);
925 ap
->a_image
[address
-ap
->a_addr
] = rtval
[i
];
927 ap
->a_used
[address
-ap
->a_addr
] = 1;
929 /* Make note of the reset vector */
930 if (!(ap
->a_flag
& A_NOLOAD
))
932 if (address
== 0xfffe)
934 execStartMSB
= rtval
[i
];
935 execStartMSBfound
= 1;
937 if (address
== 0xffff)
939 execStartLSB
= rtval
[i
];
940 execStartLSBfound
= 1;