bintools/elftools/genstubs/genstubs.cpp
author timothy.murphy@nokia.com
Fri, 30 Apr 2010 16:07:17 +0100
branchfix
changeset 511 7581d432643a
parent 0 044383f39525
permissions -rw-r--r--
fix: support new trace compiler features for preventing clashes. Automatically turn on OST_TRACE_COMPILER_IN_USE macro. Look for trace header in systemincludes. Make directories in makefile parse to prevent clashes during build. Correct path for autogen headers. Correct case issue with autogen headers on Linux.

/*
* Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of the License "Eclipse Public License v1.0"
* which accompanies this distribution, and is available
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
*
* Initial Contributors:
* Nokia Corporation - initial contribution.
*
* Contributors:
*
* Description: 
*
*/


#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#include <elfdefs.h>

#define MAXPATHNAMELENGTH 2000
#define MAXSYMBOLLENGTH 2000

#define writef(f, d, n, s) if ( 1 != fwrite(d, n, 1, f)) { croak(s); }

void croak(char * s)
{
  printf("GENSTUB ERROR: %s\n", s);
  exit(EXIT_FAILURE);
}

long codeSectionData [] = 
{
  0xe51ff004,    // LDR      pc,0x4
  0x00000000     // the pointer to the imported code
};


#define COMMENTSTRING "\tAndy's magic stub generator vsn 0.2\n"
char commentSectionData[] = // "\tAndy's magic stub generator vsn 0.2\n"
{ 
  '\t','A','n','d','y','\'','s',' ','m','a','g','i','c',' ',
  's','t','u','b',' ','g','e','n','e','r','a','t','o','r',' ',
  'v','s','n',' ','0','.','2','\n'
};

char directiveSectionData[] = // "#<SYMEDIT>\nIMPORT "
{
  '#','<','S','Y','M','E','D','I','T','>','\n',
  'I','M','P','O','R','T',' '
};

char strtabSectionData [] =
{
  0,'$','a',0,                                                          // $a
  '$','d',0,                                                            // $d
  'S','t','u','b','C','o','d','e',0,                                    // StubCode
  '.','d','i','r','e','c','t','i','v','e',0,                            // .directive
  't','h','e','I','m','p','o','r','t','e','d','S','y','m','b','o','l',0 // theImportSymbol
};

Elf32_Sym symtabSectionData[] =
{
  // undefined symbol
  {
    0, // st_name
    0, // st_value
    0, // st_size
    0, // st_info
    0, // st_other
    0  // stshndx
  },
  // $a
  {
    1, // st_name
    0, // st_value
    0, // st_size
    ELF32_ST_INFO(STB_LOCAL,STT_FUNC), // st_info
    0, // st_other
    1  // stshndx
  },
  // $d
  {
    4, // st_name
    4, // st_value
    0, // st_size
    ELF32_ST_INFO(STB_LOCAL,STT_OBJECT), // st_info
    0, // st_other
    1  // stshndx
  },
  // StubCode
  {
    7, // st_name
    0, // st_value
    sizeof(codeSectionData), // st_size
    ELF32_ST_INFO(STB_LOCAL,STT_SECTION), // st_info
    0, // st_other
    1  // stshndx
  },
  // .directive
#define DIRECTIVESYMNDX 4
  {
    16,// st_name
    0, // st_value
    0, // st_size - to be filled on
    ELF32_ST_INFO(STB_LOCAL,STT_SECTION), // st_info
    0, // st_other
    3  // stshndx
  },
  // theImportedSymbol
  {
    27, // st_name
    4, // st_value
    0, // st_size
    ELF32_ST_INFO(STB_LOCAL,STT_FUNC), // st_info
    0, // st_other
    1  // stshndx
  },

  // the exported symbol
#define EXPORTEDSYMBOLSTRNDX 45
  {
    EXPORTEDSYMBOLSTRNDX, // st_name
    0, // st_value
    0, // st_size
    ELF32_ST_INFO(STB_GLOBAL,STT_FUNC), // st_info
    0, // st_other
    1  // stshndx
  },
  // the imported symbol
#define IMPORTEDSYMBOLSYMNDX 7
  {
    0, // st_name - needs to be filled in = EXPORTEDSYMBOLSTRNDX + strlen(exportedSymbol) + 1
    0, // st_value
    0, // st_size
    ELF32_ST_INFO(STB_GLOBAL,STT_NOTYPE), // st_info
    0, // st_other
    SHN_UNDEF  // stshndx
  }
};

Elf32_Rel relocSectionData [] =
{
  {
    0x00000004, // r_offset
    ELF32_R_INFO(IMPORTEDSYMBOLSYMNDX, R_ARM_ABS32)
  }
};

char shstrtabSectionData []= 
{
  0,'S','t','u','b','C','o','d','e',0,                 // StubCode
  '.','r','e','l','S','t','u','b','C','o','d','e',0,   // .relStubCode
  '.','d','i','r','e','c','t','i','v','e',0,           // .directive
  '.','s','y','m','t','a','b',0,                       // .symtab
  '.','s','t','r','t','a','b',0,                       // .strtab
  '.','c','o','m','m','e','n','t',0,                  // .comment
  '.','s','h','s','t','r','t','a','b',0                // .shstrtab
};

Elf32_Shdr SectionHeaderTable[] = 
{
  // dummy section
  {
    0,             // sh_name - to be filled
    SHT_NULL,      // sh_type
    0,             // sh_flags
    0,             // sh_addr
    0,             // sh_offset - file offset of this section - to be filled in
    0,             // sh_size - to be filled in
    0,             // sh_link
    0,             // sh_info
    0,             // sh_addralign
    0              // sh_entsize
  },

  // StubCode section
#define CODEINDEX 1
#define CODEOFFSET (sizeof(Elf32_Ehdr) + (8 * sizeof(Elf32_Shdr)))
#define CODESIZE (sizeof(codeSectionData))
  {
    1,             // sh_name 
    SHT_PROGBITS,  // sh_type
    SHF_ALLOC + SHF_EXECINSTR, // sh_flags
    0,             // sh_addr
    CODEOFFSET,    // sh_offset 
    CODESIZE,      // sh_size
    SHN_UNDEF,     // sh_link
    0,             // sh_info
    4,             // sh_addralign
    0              // sh_entsize
  },

  // relocation data
#define RELOCINDEX 2
#define RELOCOFFSET (CODEOFFSET + CODESIZE)
#define RELOCSIZE (sizeof(relocSectionData))
  {
    10,            // sh_name - to be filled
    SHT_REL,       // sh_type
    0,             // sh_flags
    0,             // sh_addr
    RELOCOFFSET,   // sh_offset - file offset of this section - to be filled in
    RELOCSIZE,     // sh_size - there's only one of them
    3,             // sh_link - index of the symbol table we use
    1,             // sh_info - refers to section 1
    0,             // sh_addralign
    sizeof(Elf32_Rel) // sh_entsize
  },

  // .symtab
#define SYMTABINDEX 3
#define SYMTABOFFSET (RELOCOFFSET + RELOCSIZE)
#define SYMTABSIZE sizeof(symtabSectionData)
{
    34,            // sh_name 
    SHT_SYMTAB,    // sh_type
    0,             // sh_flags
    0,             // sh_addr
    SYMTABOFFSET,  // sh_offset
    SYMTABSIZE, // sh_size
    7,             // sh_link - .strtab - the string table section
    6,             // sh_info - last local symbol
    0,             // sh_addralign
    sizeof(Elf32_Sym)// sh_entsize
  },

  // .comment
#define COMMENTINDEX 4
#define COMMENTOFFSET (SYMTABOFFSET + SYMTABSIZE)
#define COMMENTSIZE (sizeof(commentSectionData))
{
    50,            // sh_name 
    SHT_PROGBITS,  // sh_type
    0,             // sh_flags
    0,             // sh_addr
    COMMENTOFFSET, // sh_offset
    COMMENTSIZE,   // sh_size - to be filled in
    SHN_UNDEF,     // sh_link
    0,             // sh_info
    0,             // sh_addralign
    0              // sh_entsize
  },


  // .shstrtab
#define SHSTRTABINDEX 5
#define SHSTRTABOFFSET (COMMENTOFFSET + COMMENTSIZE)
#define SHSTRTABSIZE sizeof(shstrtabSectionData)
  {
    59,            // sh_name 
    SHT_STRTAB,    // sh_type
    0,             // sh_flags
    0,             // sh_addr
    SHSTRTABOFFSET,// sh_offset
    SHSTRTABSIZE,  // sh_size - to be filled in
    SHN_UNDEF,     // sh_link
    0,             // sh_info
    0,             // sh_addralign
    0              // sh_entsize
      },

  // .directive section
#define DIRECTIVEINDEX 6
#define DIRECTIVEOFFSET SHSTRTABOFFSET + SHSTRTABSIZE
  {
    23,            // sh_name 
    SHT_PROGBITS,  // sh_type
    0,             // sh_flags
    0,             // sh_addr
    DIRECTIVEOFFSET,// sh_offset
    0,             // sh_size - to be filled in
    SHN_UNDEF,     // sh_link 
    0,             // sh_info 
    1,             // sh_addralign
    0              // sh_entsize
  },

  // .strtab
#define STRTABINDEX 7
  {
    42,            // sh_name
    SHT_STRTAB,    // sh_type
    0,             // sh_flags
    0,             // sh_addr
    0,             // sh_offset - to be filled in
    0,             // sh_size - to be filled in
    SHN_UNDEF,     // sh_link
    0,             // sh_info
    0,             // sh_addralign
    0              // sh_entsize
  }
};

#define ELFOBJECTFILEVERSION 1
#define EF_NONE 0x02000000

Elf32_Ehdr headerTemplate = 
{
  {0x7f, 'E', 'L', 'F', 
   ELFCLASS32, ELFDATA2LSB, ELFOBJECTFILEVERSION, 0,
   0, 0, 0, 0,
   0, 0, 0, 0},       // e_ident
  ET_REL,             // e_type
  EM_ARM,             // e_machine
  EV_CURRENT,         // e_version
  0x00000000,         // e_entry
  0,                  // e_phoff
  sizeof(Elf32_Ehdr), // e_shoff
  EF_ARM_EABI_VERSION,// e_flags
  sizeof(Elf32_Ehdr), // e_ehsize
  sizeof(Elf32_Phdr), // e_phentsize
  0,                  // e_phnum
  sizeof(Elf32_Shdr), // e_shentsize
#define SHNUM (sizeof(SectionHeaderTable)/sizeof(Elf32_Shdr))
  SHNUM,              // e_shnum 
  SHSTRTABINDEX       // e_shstrndx
};

void WriteElfHeader(FILE * file);
void WriteSectionHeaderTable(FILE * file);
void WriteCodeSection(FILE * file);
void WriteRelocationSection(FILE * file);
void WriteCommentSection(FILE * file);
void WriteSymtabSection(FILE * file);
void WriteShStrtabSection(FILE * file);
void WriteDirectiveSection(FILE * file, char * import);
void WriteStrtabSection(FILE * file, char * eexport, char * import);

void WriteStubFileX(FILE * file, char * eexport, char * import)
{
  int directiveSize = sizeof(directiveSectionData) + strlen(import) + 1; // terminated by a newline
  int strtabSize = sizeof(strtabSectionData) + strlen(eexport) + strlen(import) + 2; // strings are null terminated

  SectionHeaderTable[DIRECTIVEINDEX].sh_size = directiveSize;
  SectionHeaderTable[STRTABINDEX].sh_offset = DIRECTIVEOFFSET+ directiveSize;
  SectionHeaderTable[STRTABINDEX].sh_size = strtabSize;

  symtabSectionData[IMPORTEDSYMBOLSYMNDX].st_name  = EXPORTEDSYMBOLSTRNDX + strlen(eexport) + 1;

  WriteElfHeader(file);
  WriteSectionHeaderTable(file);
  WriteCodeSection(file);
  WriteRelocationSection(file);
  WriteSymtabSection(file);
  WriteCommentSection(file);
  WriteShStrtabSection(file);
  WriteDirectiveSection(file, import);
  WriteStrtabSection(file, eexport, import);
}

void WriteElfHeader(FILE * file)
{
  writef(file, &headerTemplate, sizeof(headerTemplate), "ELF header");
}

void WriteSectionHeaderTable(FILE * file)
{
  writef(file, &SectionHeaderTable, sizeof(SectionHeaderTable), "Section header table");
}

void CheckFileOffset(FILE * f, int i, char *s)
{
	int o = SectionHeaderTable[i].sh_offset;
	if (ftell(f)!= o) { croak(s); }
}

#define WriteSection(f, i, d, e1, e2) { CheckFileOffset(f, i, e1); writef(f, d, sizeof(d), e2); }

void WriteCodeSection(FILE * file)
{
  WriteSection(file, CODEINDEX, codeSectionData,"StubCode section offset incorrect", "StubCode section");
}

void WriteRelocationSection(FILE * file)
{
  WriteSection(file, RELOCINDEX, relocSectionData,".relStubCode section offset incorrect", ".relStubCode section");
}

void WriteCommentSection(FILE * file)
{
  WriteSection(file, COMMENTINDEX, commentSectionData,".comment section offset incorrect", ".comment section");
}

void WriteSymtabSection(FILE * file)
{
  WriteSection(file, SYMTABINDEX, symtabSectionData,".symtab section offset incorrect", ".symtab section");
}

void WriteShStrtabSection(FILE * file)
{
  WriteSection(file, SHSTRTABINDEX, shstrtabSectionData,".shstrtab section offset incorrect", ".shstrtab section");
}

void WriteDirectiveSection(FILE * file, char * import)
{
  WriteSection(file, DIRECTIVEINDEX, directiveSectionData,
	       ".directive section offset incorrect", ".directive section");
  fprintf(file, "%s\n", import);
}

void WriteStrtabSection(FILE * file, char * eexport, char * import)
{
  char n = 0;
  WriteSection(file, STRTABINDEX, strtabSectionData,".strtab section offset incorrect", ".strtab section");
  fprintf(file, eexport);
  fwrite(&n, sizeof(n), 1, file);
  fprintf(file, import);
  fwrite(&n, sizeof(n), 1, file);
}



void WriteStubFile(char * file, char * eexport, char * import)
{
  FILE * f = fopen(file, "wb");
  if (!f) croak("can't open output file");
  
  WriteStubFileX(f, eexport, import);

  fclose(f);
}


int  main (void)
{
  
  char file[MAXPATHNAMELENGTH], eexport[MAXSYMBOLLENGTH], import[MAXSYMBOLLENGTH];
  
  while (!feof(stdin) && !ferror(stdin)) {
    fscanf(stdin, "%s %s %s\n", file, eexport, import);
    WriteStubFile(file, eexport, import);
  }
  return EXIT_SUCCESS;
}