michael@0: /****************************************************************************** michael@0: * Copyright (C) 2009-2013, International Business Machines michael@0: * Corporation and others. All Rights Reserved. michael@0: ******************************************************************************* michael@0: */ michael@0: #include "unicode/utypes.h" michael@0: michael@0: #if U_PLATFORM_HAS_WIN32_API michael@0: # define VC_EXTRALEAN michael@0: # define WIN32_LEAN_AND_MEAN michael@0: # define NOUSER michael@0: # define NOSERVICE michael@0: # define NOIME michael@0: # define NOMCX michael@0: #include michael@0: #include michael@0: # ifdef __GNUC__ michael@0: # define WINDOWS_WITH_GNUC michael@0: # endif michael@0: #endif michael@0: michael@0: #if U_PLATFORM_IS_LINUX_BASED && U_HAVE_ELF_H michael@0: # define U_ELF michael@0: #endif michael@0: michael@0: #ifdef U_ELF michael@0: # include michael@0: # if defined(ELFCLASS64) michael@0: # define U_ELF64 michael@0: # endif michael@0: /* Old elf.h headers may not have EM_X86_64, or have EM_X8664 instead. */ michael@0: # ifndef EM_X86_64 michael@0: # define EM_X86_64 62 michael@0: # endif michael@0: # define ICU_ENTRY_OFFSET 0 michael@0: #endif michael@0: michael@0: #include michael@0: #include michael@0: #include "unicode/putil.h" michael@0: #include "cmemory.h" michael@0: #include "cstring.h" michael@0: #include "filestrm.h" michael@0: #include "toolutil.h" michael@0: #include "unicode/uclean.h" michael@0: #include "uoptions.h" michael@0: #include "pkg_genc.h" michael@0: michael@0: #define MAX_COLUMN ((uint32_t)(0xFFFFFFFFU)) michael@0: michael@0: #define HEX_0X 0 /* 0x1234 */ michael@0: #define HEX_0H 1 /* 01234h */ michael@0: michael@0: /* prototypes --------------------------------------------------------------- */ michael@0: static void michael@0: getOutFilename(const char *inFilename, const char *destdir, char *outFilename, char *entryName, const char *newSuffix, const char *optFilename); michael@0: michael@0: static uint32_t michael@0: write8(FileStream *out, uint8_t byte, uint32_t column); michael@0: michael@0: static uint32_t michael@0: write32(FileStream *out, uint32_t byte, uint32_t column); michael@0: michael@0: #if U_PLATFORM == U_PF_OS400 michael@0: static uint32_t michael@0: write8str(FileStream *out, uint8_t byte, uint32_t column); michael@0: #endif michael@0: /* -------------------------------------------------------------------------- */ michael@0: michael@0: /* michael@0: Creating Template Files for New Platforms michael@0: michael@0: Let the cc compiler help you get started. michael@0: Compile this program michael@0: const unsigned int x[5] = {1, 2, 0xdeadbeef, 0xffffffff, 16}; michael@0: with the -S option to produce assembly output. michael@0: michael@0: For example, this will generate array.s: michael@0: gcc -S array.c michael@0: michael@0: This will produce a .s file that may look like this: michael@0: michael@0: .file "array.c" michael@0: .version "01.01" michael@0: gcc2_compiled.: michael@0: .globl x michael@0: .section .rodata michael@0: .align 4 michael@0: .type x,@object michael@0: .size x,20 michael@0: x: michael@0: .long 1 michael@0: .long 2 michael@0: .long -559038737 michael@0: .long -1 michael@0: .long 16 michael@0: .ident "GCC: (GNU) 2.96 20000731 (Red Hat Linux 7.1 2.96-85)" michael@0: michael@0: which gives a starting point that will compile, and can be transformed michael@0: to become the template, generally with some consulting of as docs and michael@0: some experimentation. michael@0: michael@0: If you want ICU to automatically use this assembly, you should michael@0: specify "GENCCODE_ASSEMBLY=-a name" in the specific config/mh-* file, michael@0: where the name is the compiler or platform that you used in this michael@0: assemblyHeader data structure. michael@0: */ michael@0: static const struct AssemblyType { michael@0: const char *name; michael@0: const char *header; michael@0: const char *beginLine; michael@0: const char *footer; michael@0: int8_t hexType; /* HEX_0X or HEX_0h */ michael@0: } assemblyHeader[] = { michael@0: // For gcc assemblers, the meaning of .align changes depending on the michael@0: // hardware, so we use .balign 16 which always means 16 bytes. michael@0: // https://sourceware.org/binutils/docs/as/Pseudo-Ops.html michael@0: {"gcc", michael@0: ".globl %s\n" michael@0: "\t.section .note.GNU-stack,\"\",%%progbits\n" michael@0: "\t.section .rodata\n" michael@0: "\t.balign 16\n" michael@0: "\t.type %s,%%object\n" michael@0: "%s:\n\n", michael@0: michael@0: ".long ","",HEX_0X michael@0: }, michael@0: {"gcc-darwin", michael@0: /*"\t.section __TEXT,__text,regular,pure_instructions\n" michael@0: "\t.section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32\n"*/ michael@0: ".globl _%s\n" michael@0: "\t.data\n" michael@0: "\t.const\n" michael@0: "\t.balign 16\n" michael@0: "_%s:\n\n", michael@0: michael@0: ".long ","",HEX_0X michael@0: }, michael@0: {"gcc-cygwin", michael@0: ".globl _%s\n" michael@0: "\t.section .rodata\n" michael@0: "\t.balign 16\n" michael@0: "_%s:\n\n", michael@0: michael@0: ".long ","",HEX_0X michael@0: }, michael@0: {"gcc-mingw64", michael@0: ".globl %s\n" michael@0: "\t.section .rodata\n" michael@0: "\t.balign 16\n" michael@0: "%s:\n\n", michael@0: michael@0: ".long ","",HEX_0X michael@0: }, michael@0: // 16 bytes alignment. michael@0: // http://docs.oracle.com/cd/E19641-01/802-1947/802-1947.pdf michael@0: {"sun", michael@0: "\t.section \".rodata\"\n" michael@0: "\t.align 16\n" michael@0: ".globl %s\n" michael@0: "%s:\n", michael@0: michael@0: ".word ","",HEX_0X michael@0: }, michael@0: // 16 bytes alignment for sun-x86. michael@0: // http://docs.oracle.com/cd/E19963-01/html/821-1608/eoiyg.html michael@0: {"sun-x86", michael@0: "Drodata.rodata:\n" michael@0: "\t.type Drodata.rodata,@object\n" michael@0: "\t.size Drodata.rodata,0\n" michael@0: "\t.globl %s\n" michael@0: "\t.align 16\n" michael@0: "%s:\n", michael@0: michael@0: ".4byte ","",HEX_0X michael@0: }, michael@0: // 1<<4 bit alignment for aix. michael@0: // http://pic.dhe.ibm.com/infocenter/aix/v6r1/index.jsp?topic=%2Fcom.ibm.aix.aixassem%2Fdoc%2Falangref%2Fidalangref_csect_pseudoop.htm michael@0: {"xlc", michael@0: ".globl %s{RO}\n" michael@0: "\t.toc\n" michael@0: "%s:\n" michael@0: "\t.csect %s{RO}, 4\n", michael@0: michael@0: ".long ","",HEX_0X michael@0: }, michael@0: {"aCC-ia64", michael@0: "\t.file \"%s.s\"\n" michael@0: "\t.type %s,@object\n" michael@0: "\t.global %s\n" michael@0: "\t.secalias .abe$0.rodata, \".rodata\"\n" michael@0: "\t.section .abe$0.rodata = \"a\", \"progbits\"\n" michael@0: "\t.align 16\n" michael@0: "%s::\t", michael@0: michael@0: "data4 ","",HEX_0X michael@0: }, michael@0: {"aCC-parisc", michael@0: "\t.SPACE $TEXT$\n" michael@0: "\t.SUBSPA $LIT$\n" michael@0: "%s\n" michael@0: "\t.EXPORT %s\n" michael@0: "\t.ALIGN 16\n", michael@0: michael@0: ".WORD ","",HEX_0X michael@0: }, michael@0: // align 16 bytes michael@0: // http://msdn.microsoft.com/en-us/library/dwa9fwef.aspx michael@0: { "masm", michael@0: "\tTITLE %s\n" michael@0: "; generated by genccode\n" michael@0: ".386\n" michael@0: ".model flat\n" michael@0: "\tPUBLIC _%s\n" michael@0: "ICUDATA_%s\tSEGMENT READONLY PARA PUBLIC FLAT 'DATA'\n" michael@0: "\tALIGN 16\n" michael@0: "_%s\tLABEL DWORD\n", michael@0: "\tDWORD ","\nICUDATA_%s\tENDS\n\tEND\n",HEX_0H michael@0: } michael@0: }; michael@0: michael@0: static int32_t assemblyHeaderIndex = -1; michael@0: static int32_t hexType = HEX_0X; michael@0: michael@0: U_CAPI UBool U_EXPORT2 michael@0: checkAssemblyHeaderName(const char* optAssembly) { michael@0: int32_t idx; michael@0: assemblyHeaderIndex = -1; michael@0: for (idx = 0; idx < (int32_t)(sizeof(assemblyHeader)/sizeof(assemblyHeader[0])); idx++) { michael@0: if (uprv_strcmp(optAssembly, assemblyHeader[idx].name) == 0) { michael@0: assemblyHeaderIndex = idx; michael@0: hexType = assemblyHeader[idx].hexType; /* set the hex type */ michael@0: return TRUE; michael@0: } michael@0: } michael@0: michael@0: return FALSE; michael@0: } michael@0: michael@0: michael@0: U_CAPI void U_EXPORT2 michael@0: printAssemblyHeadersToStdErr(void) { michael@0: int32_t idx; michael@0: fprintf(stderr, "%s", assemblyHeader[0].name); michael@0: for (idx = 1; idx < (int32_t)(sizeof(assemblyHeader)/sizeof(assemblyHeader[0])); idx++) { michael@0: fprintf(stderr, ", %s", assemblyHeader[idx].name); michael@0: } michael@0: fprintf(stderr, michael@0: ")\n"); michael@0: } michael@0: michael@0: U_CAPI void U_EXPORT2 michael@0: writeAssemblyCode(const char *filename, const char *destdir, const char *optEntryPoint, const char *optFilename, char *outFilePath) { michael@0: uint32_t column = MAX_COLUMN; michael@0: char entry[64]; michael@0: uint32_t buffer[1024]; michael@0: char *bufferStr = (char *)buffer; michael@0: FileStream *in, *out; michael@0: size_t i, length; michael@0: michael@0: in=T_FileStream_open(filename, "rb"); michael@0: if(in==NULL) { michael@0: fprintf(stderr, "genccode: unable to open input file %s\n", filename); michael@0: exit(U_FILE_ACCESS_ERROR); michael@0: } michael@0: michael@0: getOutFilename(filename, destdir, bufferStr, entry, ".s", optFilename); michael@0: out=T_FileStream_open(bufferStr, "w"); michael@0: if(out==NULL) { michael@0: fprintf(stderr, "genccode: unable to open output file %s\n", bufferStr); michael@0: exit(U_FILE_ACCESS_ERROR); michael@0: } michael@0: michael@0: if (outFilePath != NULL) { michael@0: uprv_strcpy(outFilePath, bufferStr); michael@0: } michael@0: michael@0: #ifdef WINDOWS_WITH_GNUC michael@0: /* Need to fix the file seperator character when using MinGW. */ michael@0: swapFileSepChar(outFilePath, U_FILE_SEP_CHAR, '/'); michael@0: #endif michael@0: michael@0: if(optEntryPoint != NULL) { michael@0: uprv_strcpy(entry, optEntryPoint); michael@0: uprv_strcat(entry, "_dat"); michael@0: } michael@0: michael@0: /* turn dashes or dots in the entry name into underscores */ michael@0: length=uprv_strlen(entry); michael@0: for(i=0; i= 0 ; i--) michael@0: #endif michael@0: { michael@0: uint8_t value = ptrIdx[i]; michael@0: if (value || seenNonZero) { michael@0: *(s++)=hexToStr[value>>4]; michael@0: *(s++)=hexToStr[value&0xF]; michael@0: seenNonZero = 1; michael@0: } michael@0: } michael@0: if(hexType==HEX_0H) { michael@0: *(s++)='h'; michael@0: } michael@0: } michael@0: michael@0: *(s++)=0; michael@0: T_FileStream_writeLine(out, bitFieldStr); michael@0: return column; michael@0: } michael@0: michael@0: static uint32_t michael@0: write8(FileStream *out, uint8_t byte, uint32_t column) { michael@0: char s[4]; michael@0: int i=0; michael@0: michael@0: /* convert the byte value to a string */ michael@0: if(byte>=100) { michael@0: s[i++]=(char)('0'+byte/100); michael@0: byte%=100; michael@0: } michael@0: if(i>0 || byte>=10) { michael@0: s[i++]=(char)('0'+byte/10); michael@0: byte%=10; michael@0: } michael@0: s[i++]=(char)('0'+byte); michael@0: s[i]=0; michael@0: michael@0: /* write the value, possibly with comma and newline */ michael@0: if(column==MAX_COLUMN) { michael@0: /* first byte */ michael@0: column=1; michael@0: } else if(column<16) { michael@0: T_FileStream_writeLine(out, ","); michael@0: ++column; michael@0: } else { michael@0: T_FileStream_writeLine(out, ",\n"); michael@0: column=1; michael@0: } michael@0: T_FileStream_writeLine(out, s); michael@0: return column; michael@0: } michael@0: michael@0: #if U_PLATFORM == U_PF_OS400 michael@0: static uint32_t michael@0: write8str(FileStream *out, uint8_t byte, uint32_t column) { michael@0: char s[8]; michael@0: michael@0: if (byte > 7) michael@0: sprintf(s, "\\x%X", byte); michael@0: else michael@0: sprintf(s, "\\%X", byte); michael@0: michael@0: /* write the value, possibly with comma and newline */ michael@0: if(column==MAX_COLUMN) { michael@0: /* first byte */ michael@0: column=1; michael@0: T_FileStream_writeLine(out, "\""); michael@0: } else if(column<24) { michael@0: ++column; michael@0: } else { michael@0: T_FileStream_writeLine(out, "\"\n\""); michael@0: column=1; michael@0: } michael@0: T_FileStream_writeLine(out, s); michael@0: return column; michael@0: } michael@0: #endif michael@0: michael@0: static void michael@0: getOutFilename(const char *inFilename, const char *destdir, char *outFilename, char *entryName, const char *newSuffix, const char *optFilename) { michael@0: const char *basename=findBasename(inFilename), *suffix=uprv_strrchr(basename, '.'); michael@0: michael@0: /* copy path */ michael@0: if(destdir!=NULL && *destdir!=0) { michael@0: do { michael@0: *outFilename++=*destdir++; michael@0: } while(*destdir!=0); michael@0: if(*(outFilename-1)!=U_FILE_SEP_CHAR) { michael@0: *outFilename++=U_FILE_SEP_CHAR; michael@0: } michael@0: inFilename=basename; michael@0: } else { michael@0: while(inFilenameELFCLASS64 michael@0: ) { michael@0: fprintf(stderr, "genccode: match-arch file %s is not an ELF object file, or not supported\n", filename); michael@0: exit(U_UNSUPPORTED_ERROR); michael@0: } michael@0: michael@0: *pBits= buffer.header32.e_ident[EI_CLASS]==ELFCLASS32 ? 32 : 64; /* only 32 or 64: see check above */ michael@0: #ifdef U_ELF64 michael@0: if(*pBits!=32 && *pBits!=64) { michael@0: fprintf(stderr, "genccode: currently only supports 32-bit and 64-bit ELF format\n"); michael@0: exit(U_UNSUPPORTED_ERROR); michael@0: } michael@0: #else michael@0: if(*pBits!=32) { michael@0: fprintf(stderr, "genccode: built with elf.h missing 64-bit definitions\n"); michael@0: exit(U_UNSUPPORTED_ERROR); michael@0: } michael@0: #endif michael@0: michael@0: *pIsBigEndian=(UBool)(buffer.header32.e_ident[EI_DATA]==ELFDATA2MSB); michael@0: if(*pIsBigEndian!=U_IS_BIG_ENDIAN) { michael@0: fprintf(stderr, "genccode: currently only same-endianness ELF formats are supported\n"); michael@0: exit(U_UNSUPPORTED_ERROR); michael@0: } michael@0: /* TODO: Support byte swapping */ michael@0: michael@0: *pCPU=buffer.header32.e_machine; michael@0: #elif U_PLATFORM_HAS_WIN32_API michael@0: if(lengthMachine; michael@0: /* michael@0: * The number of bits is implicit with the Machine value. michael@0: * *pBits is ignored in the calling code, so this need not be precise. michael@0: */ michael@0: *pBits= *pCPU==IMAGE_FILE_MACHINE_I386 ? 32 : 64; michael@0: /* Windows always runs on little-endian CPUs. */ michael@0: *pIsBigEndian=FALSE; michael@0: #else michael@0: # error "Unknown platform for CAN_GENERATE_OBJECTS." michael@0: #endif michael@0: michael@0: T_FileStream_close(in); michael@0: } michael@0: michael@0: U_CAPI void U_EXPORT2 michael@0: writeObjectCode(const char *filename, const char *destdir, const char *optEntryPoint, const char *optMatchArch, const char *optFilename, char *outFilePath) { michael@0: /* common variables */ michael@0: char buffer[4096], entry[40]={ 0 }; michael@0: FileStream *in, *out; michael@0: const char *newSuffix; michael@0: int32_t i, entryLength, length, size, entryOffset=0, entryLengthOffset=0; michael@0: michael@0: uint16_t cpu, bits; michael@0: UBool makeBigEndian; michael@0: michael@0: /* platform-specific variables and initialization code */ michael@0: #ifdef U_ELF michael@0: /* 32-bit Elf file header */ michael@0: static Elf32_Ehdr header32={ michael@0: { michael@0: /* e_ident[] */ michael@0: ELFMAG0, ELFMAG1, ELFMAG2, ELFMAG3, michael@0: ELFCLASS32, michael@0: U_IS_BIG_ENDIAN ? ELFDATA2MSB : ELFDATA2LSB, michael@0: EV_CURRENT /* EI_VERSION */ michael@0: }, michael@0: ET_REL, michael@0: EM_386, michael@0: EV_CURRENT, /* e_version */ michael@0: 0, /* e_entry */ michael@0: 0, /* e_phoff */ michael@0: (Elf32_Off)sizeof(Elf32_Ehdr), /* e_shoff */ michael@0: 0, /* e_flags */ michael@0: (Elf32_Half)sizeof(Elf32_Ehdr), /* eh_size */ michael@0: 0, /* e_phentsize */ michael@0: 0, /* e_phnum */ michael@0: (Elf32_Half)sizeof(Elf32_Shdr), /* e_shentsize */ michael@0: 5, /* e_shnum */ michael@0: 2 /* e_shstrndx */ michael@0: }; michael@0: michael@0: /* 32-bit Elf section header table */ michael@0: static Elf32_Shdr sectionHeaders32[5]={ michael@0: { /* SHN_UNDEF */ michael@0: 0 michael@0: }, michael@0: { /* .symtab */ michael@0: 1, /* sh_name */ michael@0: SHT_SYMTAB, michael@0: 0, /* sh_flags */ michael@0: 0, /* sh_addr */ michael@0: (Elf32_Off)(sizeof(header32)+sizeof(sectionHeaders32)), /* sh_offset */ michael@0: (Elf32_Word)(2*sizeof(Elf32_Sym)), /* sh_size */ michael@0: 3, /* sh_link=sect hdr index of .strtab */ michael@0: 1, /* sh_info=One greater than the symbol table index of the last michael@0: * local symbol (with STB_LOCAL). */ michael@0: 4, /* sh_addralign */ michael@0: (Elf32_Word)(sizeof(Elf32_Sym)) /* sh_entsize */ michael@0: }, michael@0: { /* .shstrtab */ michael@0: 9, /* sh_name */ michael@0: SHT_STRTAB, michael@0: 0, /* sh_flags */ michael@0: 0, /* sh_addr */ michael@0: (Elf32_Off)(sizeof(header32)+sizeof(sectionHeaders32)+2*sizeof(Elf32_Sym)), /* sh_offset */ michael@0: 40, /* sh_size */ michael@0: 0, /* sh_link */ michael@0: 0, /* sh_info */ michael@0: 1, /* sh_addralign */ michael@0: 0 /* sh_entsize */ michael@0: }, michael@0: { /* .strtab */ michael@0: 19, /* sh_name */ michael@0: SHT_STRTAB, michael@0: 0, /* sh_flags */ michael@0: 0, /* sh_addr */ michael@0: (Elf32_Off)(sizeof(header32)+sizeof(sectionHeaders32)+2*sizeof(Elf32_Sym)+40), /* sh_offset */ michael@0: (Elf32_Word)sizeof(entry), /* sh_size */ michael@0: 0, /* sh_link */ michael@0: 0, /* sh_info */ michael@0: 1, /* sh_addralign */ michael@0: 0 /* sh_entsize */ michael@0: }, michael@0: { /* .rodata */ michael@0: 27, /* sh_name */ michael@0: SHT_PROGBITS, michael@0: SHF_ALLOC, /* sh_flags */ michael@0: 0, /* sh_addr */ michael@0: (Elf32_Off)(sizeof(header32)+sizeof(sectionHeaders32)+2*sizeof(Elf32_Sym)+40+sizeof(entry)), /* sh_offset */ michael@0: 0, /* sh_size */ michael@0: 0, /* sh_link */ michael@0: 0, /* sh_info */ michael@0: 16, /* sh_addralign */ michael@0: 0 /* sh_entsize */ michael@0: } michael@0: }; michael@0: michael@0: /* symbol table */ michael@0: static Elf32_Sym symbols32[2]={ michael@0: { /* STN_UNDEF */ michael@0: 0 michael@0: }, michael@0: { /* data entry point */ michael@0: 1, /* st_name */ michael@0: 0, /* st_value */ michael@0: 0, /* st_size */ michael@0: ELF64_ST_INFO(STB_GLOBAL, STT_OBJECT), michael@0: 0, /* st_other */ michael@0: 4 /* st_shndx=index of related section table entry */ michael@0: } michael@0: }; michael@0: michael@0: /* section header string table, with decimal string offsets */ michael@0: static const char sectionStrings[40]= michael@0: /* 0 */ "\0" michael@0: /* 1 */ ".symtab\0" michael@0: /* 9 */ ".shstrtab\0" michael@0: /* 19 */ ".strtab\0" michael@0: /* 27 */ ".rodata\0" michael@0: /* 35 */ "\0\0\0\0"; /* contains terminating NUL */ michael@0: /* 40: padded to multiple of 8 bytes */ michael@0: michael@0: /* michael@0: * Use entry[] for the string table which will contain only the michael@0: * entry point name. michael@0: * entry[0] must be 0 (NUL) michael@0: * The entry point name can be up to 38 characters long (sizeof(entry)-2). michael@0: */ michael@0: michael@0: /* 16-align .rodata in the .o file, just in case */ michael@0: static const char padding[16]={ 0 }; michael@0: int32_t paddingSize; michael@0: michael@0: #ifdef U_ELF64 michael@0: /* 64-bit Elf file header */ michael@0: static Elf64_Ehdr header64={ michael@0: { michael@0: /* e_ident[] */ michael@0: ELFMAG0, ELFMAG1, ELFMAG2, ELFMAG3, michael@0: ELFCLASS64, michael@0: U_IS_BIG_ENDIAN ? ELFDATA2MSB : ELFDATA2LSB, michael@0: EV_CURRENT /* EI_VERSION */ michael@0: }, michael@0: ET_REL, michael@0: EM_X86_64, michael@0: EV_CURRENT, /* e_version */ michael@0: 0, /* e_entry */ michael@0: 0, /* e_phoff */ michael@0: (Elf64_Off)sizeof(Elf64_Ehdr), /* e_shoff */ michael@0: 0, /* e_flags */ michael@0: (Elf64_Half)sizeof(Elf64_Ehdr), /* eh_size */ michael@0: 0, /* e_phentsize */ michael@0: 0, /* e_phnum */ michael@0: (Elf64_Half)sizeof(Elf64_Shdr), /* e_shentsize */ michael@0: 5, /* e_shnum */ michael@0: 2 /* e_shstrndx */ michael@0: }; michael@0: michael@0: /* 64-bit Elf section header table */ michael@0: static Elf64_Shdr sectionHeaders64[5]={ michael@0: { /* SHN_UNDEF */ michael@0: 0 michael@0: }, michael@0: { /* .symtab */ michael@0: 1, /* sh_name */ michael@0: SHT_SYMTAB, michael@0: 0, /* sh_flags */ michael@0: 0, /* sh_addr */ michael@0: (Elf64_Off)(sizeof(header64)+sizeof(sectionHeaders64)), /* sh_offset */ michael@0: (Elf64_Xword)(2*sizeof(Elf64_Sym)), /* sh_size */ michael@0: 3, /* sh_link=sect hdr index of .strtab */ michael@0: 1, /* sh_info=One greater than the symbol table index of the last michael@0: * local symbol (with STB_LOCAL). */ michael@0: 4, /* sh_addralign */ michael@0: (Elf64_Xword)(sizeof(Elf64_Sym)) /* sh_entsize */ michael@0: }, michael@0: { /* .shstrtab */ michael@0: 9, /* sh_name */ michael@0: SHT_STRTAB, michael@0: 0, /* sh_flags */ michael@0: 0, /* sh_addr */ michael@0: (Elf64_Off)(sizeof(header64)+sizeof(sectionHeaders64)+2*sizeof(Elf64_Sym)), /* sh_offset */ michael@0: 40, /* sh_size */ michael@0: 0, /* sh_link */ michael@0: 0, /* sh_info */ michael@0: 1, /* sh_addralign */ michael@0: 0 /* sh_entsize */ michael@0: }, michael@0: { /* .strtab */ michael@0: 19, /* sh_name */ michael@0: SHT_STRTAB, michael@0: 0, /* sh_flags */ michael@0: 0, /* sh_addr */ michael@0: (Elf64_Off)(sizeof(header64)+sizeof(sectionHeaders64)+2*sizeof(Elf64_Sym)+40), /* sh_offset */ michael@0: (Elf64_Xword)sizeof(entry), /* sh_size */ michael@0: 0, /* sh_link */ michael@0: 0, /* sh_info */ michael@0: 1, /* sh_addralign */ michael@0: 0 /* sh_entsize */ michael@0: }, michael@0: { /* .rodata */ michael@0: 27, /* sh_name */ michael@0: SHT_PROGBITS, michael@0: SHF_ALLOC, /* sh_flags */ michael@0: 0, /* sh_addr */ michael@0: (Elf64_Off)(sizeof(header64)+sizeof(sectionHeaders64)+2*sizeof(Elf64_Sym)+40+sizeof(entry)), /* sh_offset */ michael@0: 0, /* sh_size */ michael@0: 0, /* sh_link */ michael@0: 0, /* sh_info */ michael@0: 16, /* sh_addralign */ michael@0: 0 /* sh_entsize */ michael@0: } michael@0: }; michael@0: michael@0: /* michael@0: * 64-bit symbol table michael@0: * careful: different order of items compared with Elf32_sym! michael@0: */ michael@0: static Elf64_Sym symbols64[2]={ michael@0: { /* STN_UNDEF */ michael@0: 0 michael@0: }, michael@0: { /* data entry point */ michael@0: 1, /* st_name */ michael@0: ELF64_ST_INFO(STB_GLOBAL, STT_OBJECT), michael@0: 0, /* st_other */ michael@0: 4, /* st_shndx=index of related section table entry */ michael@0: 0, /* st_value */ michael@0: 0 /* st_size */ michael@0: } michael@0: }; michael@0: michael@0: #endif /* U_ELF64 */ michael@0: michael@0: /* entry[] have a leading NUL */ michael@0: entryOffset=1; michael@0: michael@0: /* in the common code, count entryLength from after the NUL */ michael@0: entryLengthOffset=1; michael@0: michael@0: newSuffix=".o"; michael@0: michael@0: #elif U_PLATFORM_HAS_WIN32_API michael@0: struct { michael@0: IMAGE_FILE_HEADER fileHeader; michael@0: IMAGE_SECTION_HEADER sections[2]; michael@0: char linkerOptions[100]; michael@0: } objHeader; michael@0: IMAGE_SYMBOL symbols[1]; michael@0: struct { michael@0: DWORD sizeofLongNames; michael@0: char longNames[100]; michael@0: } symbolNames; michael@0: michael@0: /* michael@0: * entry sometimes have a leading '_' michael@0: * overwritten if entryOffset==0 depending on the target platform michael@0: * see check for cpu below michael@0: */ michael@0: entry[0]='_'; michael@0: michael@0: newSuffix=".obj"; michael@0: #else michael@0: # error "Unknown platform for CAN_GENERATE_OBJECTS." michael@0: #endif michael@0: michael@0: /* deal with options, files and the entry point name */ michael@0: getArchitecture(&cpu, &bits, &makeBigEndian, optMatchArch); michael@0: printf("genccode: --match-arch cpu=%hu bits=%hu big-endian=%d\n", cpu, bits, makeBigEndian); michael@0: #if U_PLATFORM_HAS_WIN32_API michael@0: if(cpu==IMAGE_FILE_MACHINE_I386) { michael@0: entryOffset=1; michael@0: } michael@0: #endif michael@0: michael@0: in=T_FileStream_open(filename, "rb"); michael@0: if(in==NULL) { michael@0: fprintf(stderr, "genccode: unable to open input file %s\n", filename); michael@0: exit(U_FILE_ACCESS_ERROR); michael@0: } michael@0: size=T_FileStream_size(in); michael@0: michael@0: getOutFilename(filename, destdir, buffer, entry+entryOffset, newSuffix, optFilename); michael@0: if (outFilePath != NULL) { michael@0: uprv_strcpy(outFilePath, buffer); michael@0: } michael@0: michael@0: if(optEntryPoint != NULL) { michael@0: uprv_strcpy(entry+entryOffset, optEntryPoint); michael@0: uprv_strcat(entry+entryOffset, "_dat"); michael@0: } michael@0: /* turn dashes in the entry name into underscores */ michael@0: entryLength=(int32_t)uprv_strlen(entry+entryLengthOffset); michael@0: for(i=0; i