test: check removing then re-adding capabilities. Make sure output exe has the right caps.
/*
* 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;
}