1 /* lkelf.c - Create an executable ELF/DWARF file
3 Copyright (C) 2004 Erik Petrich, epetrich at users dot sourceforge dot net
5 This program is free software; you can redistribute it and/or modify it
6 under the terms of the GNU General Public License as published by the
7 Free Software Foundation; either version 3, or (at your option) any
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>. */
22 #include <asxxxx_config.h>
26 static int execStartMSB;
27 static int execStartLSB;
28 static char execStartMSBfound;
29 static char execStartLSBfound;
31 typedef TYPE_UDWORD Elf32_Addr;
32 typedef TYPE_WORD Elf32_Half;
33 typedef TYPE_UDWORD Elf32_Off;
34 typedef TYPE_DWORD Elf32_Sword;
35 typedef TYPE_UDWORD Elf32_Word;
67 /* These e_machine values are from "Motorola 8- and 16-bit Embedded */
68 /* Application Binary Interface (M8/16EABI)" version 2.0 */
117 SHF_WRITE = (1 << 0),
118 SHF_ALLOC = (1 << 1),
119 SHF_EXECINSTR = (1 << 2),
137 unsigned char e_ident[EI_NIDENT];
139 Elf32_Half e_machine;
140 Elf32_Word e_version;
146 Elf32_Half e_phentsize;
148 Elf32_Half e_shentsize;
150 Elf32_Half e_shstrndx;
163 Elf32_Word sh_addralign;
164 Elf32_Word sh_entsize;
179 typedef struct strtabString
182 struct strtabString * prev;
183 struct strtabString * next;
189 strtabString * first;
193 static strtabList shstrtab;
196 typedef struct listEntry
199 struct listEntry * prev;
200 struct listEntry * next;
213 listAdd (listHeader * lhp, void * item)
217 lep = new (sizeof (*lep));
219 lep->prev = lhp->last;
221 lep->prev->next = lep;
235 lhp = new (sizeof (*lhp));
243 strtabFind (strtabList * strtab, char * str)
250 if (!strcmp (str, sp->string))
259 /*-------------------------------------------------------------------*/
260 /* strtabFindOrAdd - Finds a string in a string table or adds the */
261 /* string if it does not already exist. Returns the offset of the */
262 /* string in the table. */
263 /*-------------------------------------------------------------------*/
265 strtabFindOrAdd (strtabList * strtab, char * str)
272 if (!strcmp (str, sp->string))
277 sp = new (sizeof(*sp));
279 sp->index = strtab->last->index + 1 + strlen (strtab->last->string);
282 sp->string = new (1+strlen (str));
283 strcpy (sp->string, str);
285 sp->prev = strtab->last;
295 /*-------------------------------------------------------------------*/
296 /* fputElfStrtab - writes a string table to a file */
297 /*-------------------------------------------------------------------*/
299 fputElfStrtab (strtabList *strtab, FILE *fp)
303 fputc (0, fp); /* index 0 must be the null character */
308 fputs (sp->string, fp);
314 /*-------------------------------------------------------------------*/
315 /* fputElf32_Word - writes an Elf32_Word value to a file */
316 /*-------------------------------------------------------------------*/
318 fputElf32_Word (Elf32_Word x, FILE *fp)
322 fputc (x & 0xff, fp);
323 fputc ((x >> 8) & 0xff, fp);
324 fputc ((x >> 16) & 0xff, fp);
325 fputc ((x >> 24) & 0xff, fp);
329 fputc ((x >> 24) & 0xff, fp);
330 fputc ((x >> 16) & 0xff, fp);
331 fputc ((x >> 8) & 0xff, fp);
332 fputc (x & 0xff, fp);
336 /*-------------------------------------------------------------------*/
337 /* fputElf32_Off - writes an Elf32_Off value to a file */
338 /*-------------------------------------------------------------------*/
340 fputElf32_Off (Elf32_Off x, FILE *fp)
344 fputc (x & 0xff, fp);
345 fputc ((x >> 8) & 0xff, fp);
346 fputc ((x >> 16) & 0xff, fp);
347 fputc ((x >> 24) & 0xff, fp);
351 fputc ((x >> 24) & 0xff, fp);
352 fputc ((x >> 16) & 0xff, fp);
353 fputc ((x >> 8) & 0xff, fp);
354 fputc (x & 0xff, fp);
358 /*-------------------------------------------------------------------*/
359 /* fputElf32_Addr - writes an Elf32_Addr value to a file */
360 /*-------------------------------------------------------------------*/
362 fputElf32_Addr (Elf32_Addr x, FILE *fp)
366 fputc (x & 0xff, fp);
367 fputc ((x >> 8) & 0xff, fp);
368 fputc ((x >> 16) & 0xff, fp);
369 fputc ((x >> 24) & 0xff, fp);
373 fputc ((x >> 24) & 0xff, fp);
374 fputc ((x >> 16) & 0xff, fp);
375 fputc ((x >> 8) & 0xff, fp);
376 fputc (x & 0xff, fp);
380 /*-------------------------------------------------------------------*/
381 /* fputElf32_Half - writes an Elf32_Half value to a file */
382 /*-------------------------------------------------------------------*/
384 fputElf32_Half (Elf32_Half x, FILE *fp)
388 fputc (x & 0xff, fp);
389 fputc ((x >> 8) & 0xff, fp);
393 fputc ((x >> 8) & 0xff, fp);
394 fputc (x & 0xff, fp);
398 /*------------------------------------------------------------------------*/
399 /* fputElf32_Ehdr - writes an Elf32_Ehdr struct (ELF header) to a file */
400 /*------------------------------------------------------------------------*/
402 fputElf32_Ehdr (Elf32_Ehdr * ehdr, FILE * fp)
406 for (i=0; i<EI_NIDENT; i++)
407 fputc (ehdr->e_ident[i], fp);
409 fputElf32_Half (ehdr->e_type, fp);
410 fputElf32_Half (ehdr->e_machine, fp);
411 fputElf32_Word (ehdr->e_version, fp);
412 fputElf32_Addr (ehdr->e_entry, fp);
413 fputElf32_Off (ehdr->e_phoff, fp);
414 fputElf32_Off (ehdr->e_shoff, fp);
415 fputElf32_Word (ehdr->e_flags, fp);
416 fputElf32_Half (ehdr->e_ehsize, fp);
417 fputElf32_Half (ehdr->e_phentsize, fp);
418 fputElf32_Half (ehdr->e_phnum, fp);
419 fputElf32_Half (ehdr->e_shentsize, fp);
420 fputElf32_Half (ehdr->e_shnum, fp);
421 fputElf32_Half (ehdr->e_shstrndx, fp);
424 /*-------------------------------------------------------------------------*/
425 /* fputElf32_Ehdr - writes an Elf32_Shdr struct (section header) to a file */
426 /*-------------------------------------------------------------------------*/
428 fputElf32_Shdr (Elf32_Shdr * shdr, FILE * fp)
430 fputElf32_Word (shdr->sh_name, fp);
431 fputElf32_Word (shdr->sh_type, fp);
432 fputElf32_Word (shdr->sh_flags, fp);
433 fputElf32_Addr (shdr->sh_addr, fp);
434 fputElf32_Off (shdr->sh_offset, fp);
435 fputElf32_Word (shdr->sh_size, fp);
436 fputElf32_Word (shdr->sh_link, fp);
437 fputElf32_Word (shdr->sh_info, fp);
438 fputElf32_Word (shdr->sh_addralign, fp);
439 fputElf32_Word (shdr->sh_entsize, fp);
442 /*-------------------------------------------------------------------------*/
443 /* fputElf32_Ehdr - writes an Elf32_Phdr struct (segment header) to a file */
444 /*-------------------------------------------------------------------------*/
446 fputElf32_Phdr (Elf32_Phdr * phdr, FILE * fp)
448 fputElf32_Word (phdr->p_type, fp);
449 fputElf32_Off (phdr->p_offset, fp);
450 fputElf32_Addr (phdr->p_vaddr, fp);
451 fputElf32_Addr (phdr->p_paddr, fp);
452 fputElf32_Word (phdr->p_filesz, fp);
453 fputElf32_Word (phdr->p_memsz, fp);
454 fputElf32_Word (phdr->p_flags, fp);
455 fputElf32_Word (phdr->p_align, fp);
459 /*--------------------------------------------------------------------------*/
460 /* elfGenerateAbs - generates segments and sections for an absolute area. */
461 /* This is a little more complicated than a relative area since it may */
462 /* contain noncontiguous regions. */
463 /*--------------------------------------------------------------------------*/
465 elfGenerateAbs (struct area *ap, listHeader * segments, listHeader * sections)
481 /* Find the start of a contiguously */
482 /* used region within this area */
483 while (ofs < ap->a_size && !ap->a_used[ofs])
485 if (ofs >= ap->a_size)
488 /* Find the end of the region */
489 addr = ap->a_addr + ofs;
490 while (ofs < ap->a_size && ap->a_used[ofs])
492 size = ap->a_addr + ofs - addr;
494 /* create a segment header for this region if loadable */
495 if (!(ap->a_flag & A_NOLOAD))
497 phdrp = new (sizeof (*phdrp));
498 phdrp->p_type = PT_LOAD;
499 phdrp->p_offset = ftell (ofp);
500 phdrp->p_vaddr = addr;
501 phdrp->p_paddr = addr;
502 phdrp->p_filesz = size;
503 phdrp->p_memsz = size;
504 phdrp->p_flags = PF_R;
505 if (ap->a_flag & A_CODE)
506 phdrp->p_flags |= PF_X;
508 listAdd (segments, phdrp);
511 /* create a section header for this region */
512 shdrp = new (sizeof (*shdrp));
513 shdrp->sh_name = strtabFindOrAdd (&shstrtab, ap->a_id);
514 shdrp->sh_type = SHT_PROGBITS;
516 if (!(ap->a_flag & A_NOLOAD))
517 shdrp->sh_flags |= SHF_ALLOC;
518 if (ap->a_flag & A_CODE)
519 shdrp->sh_flags |= SHF_EXECINSTR;
520 shdrp->sh_addr = addr;
521 shdrp->sh_offset = ftell (ofp);
522 shdrp->sh_size = size;
525 shdrp->sh_addralign = 0;
526 shdrp->sh_entsize = 0;
527 listAdd (sections, shdrp);
529 fwrite (&ap->a_image[addr-ap->a_addr], 1, size, ofp);
533 /*--------------------------------------------------------------------------*/
534 /* elfGenerateRel - generates a segment and section for a relative area. */
535 /*--------------------------------------------------------------------------*/
537 elfGenerateRel (struct area *ap, listHeader * segments, listHeader * sections)
547 /* create a segment header for this area if loadable */
548 if (!(ap->a_flag & A_NOLOAD))
550 phdrp = new (sizeof (*phdrp));
551 phdrp->p_type = PT_LOAD;
552 phdrp->p_offset = ftell (ofp);
553 phdrp->p_vaddr = ap->a_addr;
554 phdrp->p_paddr = ap->a_addr;
555 phdrp->p_filesz = ap->a_size;
556 phdrp->p_memsz = ap->a_size;
557 phdrp->p_flags = PF_R;
558 if (ap->a_flag & A_CODE)
559 phdrp->p_flags |= PF_X;
561 listAdd (segments, phdrp);
564 /* create a section header for this area */
565 shdrp = new (sizeof (*shdrp));
566 shdrp->sh_name = strtabFindOrAdd (&shstrtab, ap->a_id);
567 shdrp->sh_type = SHT_PROGBITS;
569 if (!(ap->a_flag & A_NOLOAD))
570 shdrp->sh_flags |= SHF_ALLOC;
571 if (ap->a_flag & A_CODE)
572 shdrp->sh_flags |= SHF_EXECINSTR;
573 shdrp->sh_addr = ap->a_addr;
574 shdrp->sh_offset = ftell (ofp);
575 shdrp->sh_size = ap->a_size;
578 shdrp->sh_addralign = 0;
579 shdrp->sh_entsize = 0;
580 listAdd (sections, shdrp);
582 fwrite (ap->a_image, 1, ap->a_size, ofp);
585 /*--------------------------------------------------------------------------*/
586 /* elfGenerate - generates the complete ELF file */
587 /*--------------------------------------------------------------------------*/
591 listHeader * sections = listNew();
592 listHeader * segments = listNew();
599 Elf32_Word shstrtabName;
601 /* create the null section header for index 0 */
602 shdrp = new (sizeof (*shdrp));
604 shdrp->sh_type = SHT_NULL;
607 shdrp->sh_offset = 0;
611 shdrp->sh_addralign = 0;
612 shdrp->sh_entsize = 0;
613 listAdd (sections, shdrp);
615 /* Initialize the ELF header */
616 for (i=0; i<EI_NIDENT; i++)
618 ehdr.e_ident[EI_MAG0] = ELFMAG0;
619 ehdr.e_ident[EI_MAG1] = ELFMAG1;
620 ehdr.e_ident[EI_MAG2] = ELFMAG2;
621 ehdr.e_ident[EI_MAG3] = ELFMAG3;
622 ehdr.e_ident[EI_CLASS] = ELFCLASS32;
624 ehdr.e_ident[EI_DATA] = ELFDATA2LSB;
626 ehdr.e_ident[EI_DATA] = ELFDATA2MSB;
627 ehdr.e_ident[EI_VERSION] = 1;
628 ehdr.e_type = ET_EXEC;
629 ehdr.e_machine = EM_68HC08; /* FIXME: get rid of hardcoded value - EEP */
630 ehdr.e_phentsize = sizeof (*phdrp);
631 ehdr.e_shentsize = sizeof (*shdrp);
632 ehdr.e_ehsize = sizeof (ehdr);
638 if (execStartMSBfound && execStartLSBfound)
639 ehdr.e_entry = (execStartMSB << 8) + execStartLSB;
641 /* Write out the ELF header as a placeholder; we will update */
642 /* it with the final values when everything is complete */
643 fputElf32_Ehdr (&ehdr, ofp);
645 /* Iterate over the linker areas to generate */
646 /* the ELF sections and segments */
652 if (ap->a_flag & A_ABS)
653 elfGenerateAbs (ap, segments, sections);
655 elfGenerateRel (ap, segments, sections);
660 /* Create the string table section after the other sections */
661 shdrp = new (sizeof (*shdrp));
662 shdrp->sh_name = strtabFindOrAdd (&shstrtab, ".shstrtab");
663 shdrp->sh_type = SHT_STRTAB;
666 shdrp->sh_offset = ftell (ofp);
667 shdrp->sh_size = shstrtab.last->index + strlen (shstrtab.last->string) + 1;
670 shdrp->sh_addralign = 0;
671 shdrp->sh_entsize = 0;
672 listAdd (sections, shdrp);
673 fputElfStrtab (&shstrtab, ofp);
675 /* Find the index of the section string table */
676 /* header and save it in the ELF header */
678 shstrtabName = shdrp->sh_name;
679 lep = sections->first;
683 if (shdrp->sh_name == shstrtabName)
689 /* Write out the segment headers */
690 ehdr.e_phnum = segments->count;
691 ehdr.e_phoff = ftell (ofp);
692 lep = segments->first;
696 fputElf32_Phdr (phdrp, ofp);
700 /* Write out the section headers */
701 ehdr.e_shnum = sections->count;
702 ehdr.e_shoff = ftell (ofp);
703 lep = sections->first;
707 fputElf32_Shdr (shdrp, ofp);
711 /* All the values in the ELF header have now been computed; write */
712 /* over the placeholder header with the final values */
713 fseek (ofp, 0, SEEK_SET);
714 fputElf32_Ehdr (&ehdr, ofp);
715 fseek (ofp, 0, SEEK_END);
718 /*--------------------------------------------------------------------------*/
719 /* elf - incrementally called by the linker core to generate ELF file data. */
720 /* The parameter is nonzero when there is data available and zero when */
721 /* the linker is finished. */
722 /*--------------------------------------------------------------------------*/
728 /* Buffer the data until we have it all */
732 address = rtval[0] + (rtval[1] << 8); /* little endian order */
734 address = rtval[1] + (rtval[0] << 8); /* big endian order */
736 /* If this area doesn't have an image buffer, create one */
739 ap->a_image = new (ap->a_size);
740 if (ap->a_flag & A_ABS)
741 ap->a_used = new (ap->a_size);
744 /* Copy the data into the image buffer */
745 for (i = 2; i < rtcnt ; i++)
749 ap->a_image[address-ap->a_addr] = rtval[i];
751 ap->a_used[address-ap->a_addr] = 1;
753 /* Make note of the reset vector */
754 if (!(ap->a_flag & A_NOLOAD))
756 if (address == 0xfffe)
758 execStartMSB = rtval[i];
759 execStartMSBfound = 1;
761 if (address == 0xffff)
763 execStartLSB = rtval[i];
764 execStartLSBfound = 1;