1 /******************************************************************************
2 * Copyright (C) 2009-2013, International Business Machines
3 * Corporation and others. All Rights Reserved.
4 *******************************************************************************
6 #include "unicode/utypes.h"
8 #if U_PLATFORM_HAS_WIN32_API
10 # define WIN32_LEAN_AND_MEAN
18 # define WINDOWS_WITH_GNUC
22 #if U_PLATFORM_IS_LINUX_BASED && U_HAVE_ELF_H
28 # if defined(ELFCLASS64)
31 /* Old elf.h headers may not have EM_X86_64, or have EM_X8664 instead. */
35 # define ICU_ENTRY_OFFSET 0
40 #include "unicode/putil.h"
45 #include "unicode/uclean.h"
49 #define MAX_COLUMN ((uint32_t)(0xFFFFFFFFU))
51 #define HEX_0X 0 /* 0x1234 */
52 #define HEX_0H 1 /* 01234h */
54 /* prototypes --------------------------------------------------------------- */
56 getOutFilename(const char *inFilename, const char *destdir, char *outFilename, char *entryName, const char *newSuffix, const char *optFilename);
59 write8(FileStream *out, uint8_t byte, uint32_t column);
62 write32(FileStream *out, uint32_t byte, uint32_t column);
64 #if U_PLATFORM == U_PF_OS400
66 write8str(FileStream *out, uint8_t byte, uint32_t column);
68 /* -------------------------------------------------------------------------- */
71 Creating Template Files for New Platforms
73 Let the cc compiler help you get started.
75 const unsigned int x[5] = {1, 2, 0xdeadbeef, 0xffffffff, 16};
76 with the -S option to produce assembly output.
78 For example, this will generate array.s:
81 This will produce a .s file that may look like this:
97 .ident "GCC: (GNU) 2.96 20000731 (Red Hat Linux 7.1 2.96-85)"
99 which gives a starting point that will compile, and can be transformed
100 to become the template, generally with some consulting of as docs and
101 some experimentation.
103 If you want ICU to automatically use this assembly, you should
104 specify "GENCCODE_ASSEMBLY=-a name" in the specific config/mh-* file,
105 where the name is the compiler or platform that you used in this
106 assemblyHeader data structure.
108 static const struct AssemblyType {
111 const char *beginLine;
113 int8_t hexType; /* HEX_0X or HEX_0h */
114 } assemblyHeader[] = {
115 // For gcc assemblers, the meaning of .align changes depending on the
116 // hardware, so we use .balign 16 which always means 16 bytes.
117 // https://sourceware.org/binutils/docs/as/Pseudo-Ops.html
120 "\t.section .note.GNU-stack,\"\",%%progbits\n"
121 "\t.section .rodata\n"
123 /* The 3 lines below are added for Chrome. */
124 "#ifdef U_HIDE_DATA_SYMBOL\n"
127 "\t.type %s,%%object\n"
133 /*"\t.section __TEXT,__text,regular,pure_instructions\n"
134 "\t.section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32\n"*/
136 /* The 3 lines below are added for Chrome. */
137 "#ifdef U_HIDE_DATA_SYMBOL\n"
138 "\t.private_extern _%s\n"
149 "\t.section .rodata\n"
157 "\t.section .rodata\n"
163 // 16 bytes alignment.
164 // http://docs.oracle.com/cd/E19641-01/802-1947/802-1947.pdf
166 "\t.section \".rodata\"\n"
173 // 16 bytes alignment for sun-x86.
174 // http://docs.oracle.com/cd/E19963-01/html/821-1608/eoiyg.html
177 "\t.type Drodata.rodata,@object\n"
178 "\t.size Drodata.rodata,0\n"
185 // 1<<4 bit alignment for aix.
186 // http://pic.dhe.ibm.com/infocenter/aix/v6r1/index.jsp?topic=%2Fcom.ibm.aix.aixassem%2Fdoc%2Falangref%2Fidalangref_csect_pseudoop.htm
191 "\t.csect %s{RO}, 4\n",
197 "\t.type %s,@object\n"
199 "\t.secalias .abe$0.rodata, \".rodata\"\n"
200 "\t.section .abe$0.rodata = \"a\", \"progbits\"\n"
216 // http://msdn.microsoft.com/en-us/library/dwa9fwef.aspx
219 "; generated by genccode\n"
223 "ICUDATA_%s\tSEGMENT READONLY PARA PUBLIC FLAT 'DATA'\n"
225 "_%s\tLABEL DWORD\n",
226 "\tDWORD ","\nICUDATA_%s\tENDS\n\tEND\n",HEX_0H
230 static int32_t assemblyHeaderIndex = -1;
231 static int32_t hexType = HEX_0X;
233 U_CAPI UBool U_EXPORT2
234 checkAssemblyHeaderName(const char* optAssembly) {
236 assemblyHeaderIndex = -1;
237 for (idx = 0; idx < (int32_t)(sizeof(assemblyHeader)/sizeof(assemblyHeader[0])); idx++) {
238 if (uprv_strcmp(optAssembly, assemblyHeader[idx].name) == 0) {
239 assemblyHeaderIndex = idx;
240 hexType = assemblyHeader[idx].hexType; /* set the hex type */
249 U_CAPI void U_EXPORT2
250 printAssemblyHeadersToStdErr(void) {
252 fprintf(stderr, "%s", assemblyHeader[0].name);
253 for (idx = 1; idx < (int32_t)(sizeof(assemblyHeader)/sizeof(assemblyHeader[0])); idx++) {
254 fprintf(stderr, ", %s", assemblyHeader[idx].name);
260 U_CAPI void U_EXPORT2
261 writeAssemblyCode(const char *filename, const char *destdir, const char *optEntryPoint, const char *optFilename, char *outFilePath) {
262 uint32_t column = MAX_COLUMN;
264 uint32_t buffer[1024];
265 char *bufferStr = (char *)buffer;
266 FileStream *in, *out;
269 in=T_FileStream_open(filename, "rb");
271 fprintf(stderr, "genccode: unable to open input file %s\n", filename);
272 exit(U_FILE_ACCESS_ERROR);
275 getOutFilename(filename, destdir, bufferStr, entry, ".S", optFilename);
276 out=T_FileStream_open(bufferStr, "w");
278 fprintf(stderr, "genccode: unable to open output file %s\n", bufferStr);
279 exit(U_FILE_ACCESS_ERROR);
282 if (outFilePath != NULL) {
283 uprv_strcpy(outFilePath, bufferStr);
286 #ifdef WINDOWS_WITH_GNUC
287 /* Need to fix the file seperator character when using MinGW. */
288 swapFileSepChar(outFilePath, U_FILE_SEP_CHAR, '/');
291 if(optEntryPoint != NULL) {
292 uprv_strcpy(entry, optEntryPoint);
293 uprv_strcat(entry, "_dat");
296 /* turn dashes or dots in the entry name into underscores */
297 length=uprv_strlen(entry);
298 for(i=0; i<length; ++i) {
299 if(entry[i]=='-' || entry[i]=='.') {
304 sprintf(bufferStr, assemblyHeader[assemblyHeaderIndex].header,
305 entry, entry, entry, entry,
306 entry, entry, entry, entry);
307 T_FileStream_writeLine(out, bufferStr);
308 T_FileStream_writeLine(out, assemblyHeader[assemblyHeaderIndex].beginLine);
311 length=T_FileStream_read(in, buffer, sizeof(buffer));
315 if (length != sizeof(buffer)) {
316 /* pad with extra 0's when at the end of the file */
317 for(i=0; i < (length % sizeof(uint32_t)); ++i) {
318 buffer[length+i] = 0;
321 for(i=0; i<(length/sizeof(buffer[0])); i++) {
322 column = write32(out, buffer[i], column);
326 T_FileStream_writeLine(out, "\n");
328 sprintf(bufferStr, assemblyHeader[assemblyHeaderIndex].footer,
329 entry, entry, entry, entry,
330 entry, entry, entry, entry);
331 T_FileStream_writeLine(out, bufferStr);
333 if(T_FileStream_error(in)) {
334 fprintf(stderr, "genccode: file read error while generating from file %s\n", filename);
335 exit(U_FILE_ACCESS_ERROR);
338 if(T_FileStream_error(out)) {
339 fprintf(stderr, "genccode: file write error while generating from file %s\n", filename);
340 exit(U_FILE_ACCESS_ERROR);
343 T_FileStream_close(out);
344 T_FileStream_close(in);
347 U_CAPI void U_EXPORT2
348 writeCCode(const char *filename, const char *destdir, const char *optName, const char *optFilename, char *outFilePath) {
349 uint32_t column = MAX_COLUMN;
350 char buffer[4096], entry[64];
351 FileStream *in, *out;
354 in=T_FileStream_open(filename, "rb");
356 fprintf(stderr, "genccode: unable to open input file %s\n", filename);
357 exit(U_FILE_ACCESS_ERROR);
360 if(optName != NULL) { /* prepend 'icudt28_' */
361 strcpy(entry, optName);
367 getOutFilename(filename, destdir, buffer, entry+uprv_strlen(entry), ".c", optFilename);
368 if (outFilePath != NULL) {
369 uprv_strcpy(outFilePath, buffer);
371 out=T_FileStream_open(buffer, "w");
373 fprintf(stderr, "genccode: unable to open output file %s\n", buffer);
374 exit(U_FILE_ACCESS_ERROR);
377 /* turn dashes or dots in the entry name into underscores */
378 length=uprv_strlen(entry);
379 for(i=0; i<length; ++i) {
380 if(entry[i]=='-' || entry[i]=='.') {
385 #if U_PLATFORM == U_PF_OS400
387 TODO: Fix this once the compiler implements this feature. Keep in sync with udatamem.c
389 This is here because this platform can't currently put
390 const data into the read-only pages of an object or
391 shared library (service program). Only strings are allowed in read-only
392 pages, so we use char * strings to store the data.
394 In order to prevent the beginning of the data from ever matching the
395 magic numbers we must still use the initial double.
399 "#ifndef IN_GENERATED_CCODE\n"
400 "#define IN_GENERATED_CCODE\n"
401 "#define U_DISABLE_RENAMING 1\n"
402 "#include \"unicode/umachine.h\"\n"
407 " const char *bytes; \n"
410 T_FileStream_writeLine(out, buffer);
413 length=T_FileStream_read(in, buffer, sizeof(buffer));
417 for(i=0; i<length; ++i) {
418 column = write8str(out, (uint8_t)buffer[i], column);
422 T_FileStream_writeLine(out, "\"\n};\nU_CDECL_END\n");
424 /* Function renaming shouldn't be done in data */
426 "#ifndef IN_GENERATED_CCODE\n"
427 "#define IN_GENERATED_CCODE\n"
428 "#define U_DISABLE_RENAMING 1\n"
429 "#include \"unicode/umachine.h\"\n"
434 " uint8_t bytes[%ld]; \n"
436 (long)T_FileStream_size(in), entry);
437 T_FileStream_writeLine(out, buffer);
440 length=T_FileStream_read(in, buffer, sizeof(buffer));
444 for(i=0; i<length; ++i) {
445 column = write8(out, (uint8_t)buffer[i], column);
449 T_FileStream_writeLine(out, "\n}\n};\nU_CDECL_END\n");
452 if(T_FileStream_error(in)) {
453 fprintf(stderr, "genccode: file read error while generating from file %s\n", filename);
454 exit(U_FILE_ACCESS_ERROR);
457 if(T_FileStream_error(out)) {
458 fprintf(stderr, "genccode: file write error while generating from file %s\n", filename);
459 exit(U_FILE_ACCESS_ERROR);
462 T_FileStream_close(out);
463 T_FileStream_close(in);
467 write32(FileStream *out, uint32_t bitField, uint32_t column) {
469 char bitFieldStr[64]; /* This is more bits than needed for a 32-bit number */
470 char *s = bitFieldStr;
471 uint8_t *ptrIdx = (uint8_t *)&bitField;
472 static const char hexToStr[16] = {
479 /* write the value, possibly with comma and newline */
480 if(column==MAX_COLUMN) {
483 } else if(column<32) {
488 uprv_strcpy(s, assemblyHeader[assemblyHeaderIndex].beginLine);
494 /* It's a small number. Don't waste the space for 0x */
495 *(s++)=hexToStr[bitField];
498 int seenNonZero = 0; /* This is used to remove leading zeros */
500 if(hexType==HEX_0X) {
503 } else if(hexType==HEX_0H) {
507 /* This creates a 32-bit field */
509 for (i = 0; i < sizeof(uint32_t); i++)
511 for (i = sizeof(uint32_t)-1; i >= 0 ; i--)
514 uint8_t value = ptrIdx[i];
515 if (value || seenNonZero) {
516 *(s++)=hexToStr[value>>4];
517 *(s++)=hexToStr[value&0xF];
521 if(hexType==HEX_0H) {
527 T_FileStream_writeLine(out, bitFieldStr);
532 write8(FileStream *out, uint8_t byte, uint32_t column) {
536 /* convert the byte value to a string */
538 s[i++]=(char)('0'+byte/100);
541 if(i>0 || byte>=10) {
542 s[i++]=(char)('0'+byte/10);
545 s[i++]=(char)('0'+byte);
548 /* write the value, possibly with comma and newline */
549 if(column==MAX_COLUMN) {
552 } else if(column<16) {
553 T_FileStream_writeLine(out, ",");
556 T_FileStream_writeLine(out, ",\n");
559 T_FileStream_writeLine(out, s);
563 #if U_PLATFORM == U_PF_OS400
565 write8str(FileStream *out, uint8_t byte, uint32_t column) {
569 sprintf(s, "\\x%X", byte);
571 sprintf(s, "\\%X", byte);
573 /* write the value, possibly with comma and newline */
574 if(column==MAX_COLUMN) {
577 T_FileStream_writeLine(out, "\"");
578 } else if(column<24) {
581 T_FileStream_writeLine(out, "\"\n\"");
584 T_FileStream_writeLine(out, s);
590 getOutFilename(const char *inFilename, const char *destdir, char *outFilename, char *entryName, const char *newSuffix, const char *optFilename) {
591 const char *basename=findBasename(inFilename), *suffix=uprv_strrchr(basename, '.');
594 if(destdir!=NULL && *destdir!=0) {
596 *outFilename++=*destdir++;
597 } while(*destdir!=0);
598 if(*(outFilename-1)!=U_FILE_SEP_CHAR) {
599 *outFilename++=U_FILE_SEP_CHAR;
603 while(inFilename<basename) {
604 *outFilename++=*inFilename++;
609 /* the filename does not have a suffix */
610 uprv_strcpy(entryName, inFilename);
611 if(optFilename != NULL) {
612 uprv_strcpy(outFilename, optFilename);
614 uprv_strcpy(outFilename, inFilename);
616 uprv_strcat(outFilename, newSuffix);
618 char *saveOutFilename = outFilename;
620 while(inFilename<suffix) {
621 if(*inFilename=='-') {
622 /* iSeries cannot have '-' in the .o objects. */
623 *outFilename++=*entryName++='_';
627 *outFilename++=*entryName++=*inFilename++;
631 /* replace '.' by '_' */
632 *outFilename++=*entryName++='_';
636 while(*inFilename!=0) {
637 *outFilename++=*entryName++=*inFilename++;
642 if(optFilename != NULL) {
643 uprv_strcpy(saveOutFilename, optFilename);
644 uprv_strcat(saveOutFilename, newSuffix);
647 uprv_strcpy(outFilename, newSuffix);
652 #ifdef CAN_GENERATE_OBJECTS
654 getArchitecture(uint16_t *pCPU, uint16_t *pBits, UBool *pIsBigEndian, const char *optMatchArch) {
659 /* Elf32_Ehdr and ELF64_Ehdr are identical for the necessary fields. */
660 #elif U_PLATFORM_HAS_WIN32_API
661 IMAGE_FILE_HEADER header;
665 const char *filename;
671 #elif U_PLATFORM_HAS_WIN32_API
672 const IMAGE_FILE_HEADER *pHeader;
674 # error "Unknown platform for CAN_GENERATE_OBJECTS."
677 if(optMatchArch != NULL) {
678 filename=optMatchArch;
682 /* set EM_386 because elf.h does not provide better defaults */
685 *pIsBigEndian=(UBool)(U_IS_BIG_ENDIAN ? ELFDATA2MSB : ELFDATA2LSB);
686 #elif U_PLATFORM_HAS_WIN32_API
687 /* _M_IA64 should be defined in windows.h */
688 # if defined(_M_IA64)
689 *pCPU=IMAGE_FILE_MACHINE_IA64;
690 # elif defined(_M_AMD64)
691 *pCPU=IMAGE_FILE_MACHINE_AMD64;
693 *pCPU=IMAGE_FILE_MACHINE_I386;
695 *pBits= *pCPU==IMAGE_FILE_MACHINE_I386 ? 32 : 64;
698 # error "Unknown platform for CAN_GENERATE_OBJECTS."
703 in=T_FileStream_open(filename, "rb");
705 fprintf(stderr, "genccode: unable to open match-arch file %s\n", filename);
706 exit(U_FILE_ACCESS_ERROR);
708 length=T_FileStream_read(in, buffer.bytes, sizeof(buffer.bytes));
711 if(length<sizeof(Elf32_Ehdr)) {
712 fprintf(stderr, "genccode: match-arch file %s is too short\n", filename);
713 exit(U_UNSUPPORTED_ERROR);
716 buffer.header32.e_ident[0]!=ELFMAG0 ||
717 buffer.header32.e_ident[1]!=ELFMAG1 ||
718 buffer.header32.e_ident[2]!=ELFMAG2 ||
719 buffer.header32.e_ident[3]!=ELFMAG3 ||
720 buffer.header32.e_ident[EI_CLASS]<ELFCLASS32 || buffer.header32.e_ident[EI_CLASS]>ELFCLASS64
722 fprintf(stderr, "genccode: match-arch file %s is not an ELF object file, or not supported\n", filename);
723 exit(U_UNSUPPORTED_ERROR);
726 *pBits= buffer.header32.e_ident[EI_CLASS]==ELFCLASS32 ? 32 : 64; /* only 32 or 64: see check above */
728 if(*pBits!=32 && *pBits!=64) {
729 fprintf(stderr, "genccode: currently only supports 32-bit and 64-bit ELF format\n");
730 exit(U_UNSUPPORTED_ERROR);
734 fprintf(stderr, "genccode: built with elf.h missing 64-bit definitions\n");
735 exit(U_UNSUPPORTED_ERROR);
739 *pIsBigEndian=(UBool)(buffer.header32.e_ident[EI_DATA]==ELFDATA2MSB);
740 if(*pIsBigEndian!=U_IS_BIG_ENDIAN) {
741 fprintf(stderr, "genccode: currently only same-endianness ELF formats are supported\n");
742 exit(U_UNSUPPORTED_ERROR);
744 /* TODO: Support byte swapping */
746 *pCPU=buffer.header32.e_machine;
747 #elif U_PLATFORM_HAS_WIN32_API
748 if(length<sizeof(IMAGE_FILE_HEADER)) {
749 fprintf(stderr, "genccode: match-arch file %s is too short\n", filename);
750 exit(U_UNSUPPORTED_ERROR);
752 /* TODO: Use buffer.header. Keep aliasing legal. */
753 pHeader=(const IMAGE_FILE_HEADER *)buffer.bytes;
754 *pCPU=pHeader->Machine;
756 * The number of bits is implicit with the Machine value.
757 * *pBits is ignored in the calling code, so this need not be precise.
759 *pBits= *pCPU==IMAGE_FILE_MACHINE_I386 ? 32 : 64;
760 /* Windows always runs on little-endian CPUs. */
763 # error "Unknown platform for CAN_GENERATE_OBJECTS."
766 T_FileStream_close(in);
769 U_CAPI void U_EXPORT2
770 writeObjectCode(const char *filename, const char *destdir, const char *optEntryPoint, const char *optMatchArch, const char *optFilename, char *outFilePath) {
771 /* common variables */
772 char buffer[4096], entry[40]={ 0 };
773 FileStream *in, *out;
774 const char *newSuffix;
775 int32_t i, entryLength, length, size, entryOffset=0, entryLengthOffset=0;
780 /* platform-specific variables and initialization code */
782 /* 32-bit Elf file header */
783 static Elf32_Ehdr header32={
786 ELFMAG0, ELFMAG1, ELFMAG2, ELFMAG3,
788 U_IS_BIG_ENDIAN ? ELFDATA2MSB : ELFDATA2LSB,
789 EV_CURRENT /* EI_VERSION */
793 EV_CURRENT, /* e_version */
796 (Elf32_Off)sizeof(Elf32_Ehdr), /* e_shoff */
798 (Elf32_Half)sizeof(Elf32_Ehdr), /* eh_size */
801 (Elf32_Half)sizeof(Elf32_Shdr), /* e_shentsize */
806 /* 32-bit Elf section header table */
807 static Elf32_Shdr sectionHeaders32[5]={
816 (Elf32_Off)(sizeof(header32)+sizeof(sectionHeaders32)), /* sh_offset */
817 (Elf32_Word)(2*sizeof(Elf32_Sym)), /* sh_size */
818 3, /* sh_link=sect hdr index of .strtab */
819 1, /* sh_info=One greater than the symbol table index of the last
820 * local symbol (with STB_LOCAL). */
821 4, /* sh_addralign */
822 (Elf32_Word)(sizeof(Elf32_Sym)) /* sh_entsize */
829 (Elf32_Off)(sizeof(header32)+sizeof(sectionHeaders32)+2*sizeof(Elf32_Sym)), /* sh_offset */
833 1, /* sh_addralign */
841 (Elf32_Off)(sizeof(header32)+sizeof(sectionHeaders32)+2*sizeof(Elf32_Sym)+40), /* sh_offset */
842 (Elf32_Word)sizeof(entry), /* sh_size */
845 1, /* sh_addralign */
851 SHF_ALLOC, /* sh_flags */
853 (Elf32_Off)(sizeof(header32)+sizeof(sectionHeaders32)+2*sizeof(Elf32_Sym)+40+sizeof(entry)), /* sh_offset */
857 16, /* sh_addralign */
863 static Elf32_Sym symbols32[2]={
867 { /* data entry point */
871 ELF64_ST_INFO(STB_GLOBAL, STT_OBJECT),
873 4 /* st_shndx=index of related section table entry */
877 /* section header string table, with decimal string offsets */
878 static const char sectionStrings[40]=
881 /* 9 */ ".shstrtab\0"
884 /* 35 */ "\0\0\0\0"; /* contains terminating NUL */
885 /* 40: padded to multiple of 8 bytes */
888 * Use entry[] for the string table which will contain only the
890 * entry[0] must be 0 (NUL)
891 * The entry point name can be up to 38 characters long (sizeof(entry)-2).
894 /* 16-align .rodata in the .o file, just in case */
895 static const char padding[16]={ 0 };
899 /* 64-bit Elf file header */
900 static Elf64_Ehdr header64={
903 ELFMAG0, ELFMAG1, ELFMAG2, ELFMAG3,
905 U_IS_BIG_ENDIAN ? ELFDATA2MSB : ELFDATA2LSB,
906 EV_CURRENT /* EI_VERSION */
910 EV_CURRENT, /* e_version */
913 (Elf64_Off)sizeof(Elf64_Ehdr), /* e_shoff */
915 (Elf64_Half)sizeof(Elf64_Ehdr), /* eh_size */
918 (Elf64_Half)sizeof(Elf64_Shdr), /* e_shentsize */
923 /* 64-bit Elf section header table */
924 static Elf64_Shdr sectionHeaders64[5]={
933 (Elf64_Off)(sizeof(header64)+sizeof(sectionHeaders64)), /* sh_offset */
934 (Elf64_Xword)(2*sizeof(Elf64_Sym)), /* sh_size */
935 3, /* sh_link=sect hdr index of .strtab */
936 1, /* sh_info=One greater than the symbol table index of the last
937 * local symbol (with STB_LOCAL). */
938 4, /* sh_addralign */
939 (Elf64_Xword)(sizeof(Elf64_Sym)) /* sh_entsize */
946 (Elf64_Off)(sizeof(header64)+sizeof(sectionHeaders64)+2*sizeof(Elf64_Sym)), /* sh_offset */
950 1, /* sh_addralign */
958 (Elf64_Off)(sizeof(header64)+sizeof(sectionHeaders64)+2*sizeof(Elf64_Sym)+40), /* sh_offset */
959 (Elf64_Xword)sizeof(entry), /* sh_size */
962 1, /* sh_addralign */
968 SHF_ALLOC, /* sh_flags */
970 (Elf64_Off)(sizeof(header64)+sizeof(sectionHeaders64)+2*sizeof(Elf64_Sym)+40+sizeof(entry)), /* sh_offset */
974 16, /* sh_addralign */
980 * 64-bit symbol table
981 * careful: different order of items compared with Elf32_sym!
983 static Elf64_Sym symbols64[2]={
987 { /* data entry point */
989 ELF64_ST_INFO(STB_GLOBAL, STT_OBJECT),
991 4, /* st_shndx=index of related section table entry */
999 /* entry[] have a leading NUL */
1002 /* in the common code, count entryLength from after the NUL */
1003 entryLengthOffset=1;
1007 #elif U_PLATFORM_HAS_WIN32_API
1009 IMAGE_FILE_HEADER fileHeader;
1010 IMAGE_SECTION_HEADER sections[2];
1011 char linkerOptions[100];
1013 IMAGE_SYMBOL symbols[1];
1015 DWORD sizeofLongNames;
1016 char longNames[100];
1020 * entry sometimes have a leading '_'
1021 * overwritten if entryOffset==0 depending on the target platform
1022 * see check for cpu below
1028 # error "Unknown platform for CAN_GENERATE_OBJECTS."
1031 /* deal with options, files and the entry point name */
1032 getArchitecture(&cpu, &bits, &makeBigEndian, optMatchArch);
1033 printf("genccode: --match-arch cpu=%hu bits=%hu big-endian=%d\n", cpu, bits, makeBigEndian);
1034 #if U_PLATFORM_HAS_WIN32_API
1035 if(cpu==IMAGE_FILE_MACHINE_I386) {
1040 in=T_FileStream_open(filename, "rb");
1042 fprintf(stderr, "genccode: unable to open input file %s\n", filename);
1043 exit(U_FILE_ACCESS_ERROR);
1045 size=T_FileStream_size(in);
1047 getOutFilename(filename, destdir, buffer, entry+entryOffset, newSuffix, optFilename);
1048 if (outFilePath != NULL) {
1049 uprv_strcpy(outFilePath, buffer);
1052 if(optEntryPoint != NULL) {
1053 uprv_strcpy(entry+entryOffset, optEntryPoint);
1054 uprv_strcat(entry+entryOffset, "_dat");
1056 /* turn dashes in the entry name into underscores */
1057 entryLength=(int32_t)uprv_strlen(entry+entryLengthOffset);
1058 for(i=0; i<entryLength; ++i) {
1059 if(entry[entryLengthOffset+i]=='-') {
1060 entry[entryLengthOffset+i]='_';
1064 /* open the output file */
1065 out=T_FileStream_open(buffer, "wb");
1067 fprintf(stderr, "genccode: unable to open output file %s\n", buffer);
1068 exit(U_FILE_ACCESS_ERROR);
1073 header32.e_ident[EI_DATA]= makeBigEndian ? ELFDATA2MSB : ELFDATA2LSB;
1074 header32.e_machine=cpu;
1076 /* 16-align .rodata in the .o file, just in case */
1077 paddingSize=sectionHeaders32[4].sh_offset & 0xf;
1078 if(paddingSize!=0) {
1079 paddingSize=0x10-paddingSize;
1080 sectionHeaders32[4].sh_offset+=paddingSize;
1083 sectionHeaders32[4].sh_size=(Elf32_Word)size;
1085 symbols32[1].st_size=(Elf32_Word)size;
1087 /* write .o headers */
1088 T_FileStream_write(out, &header32, (int32_t)sizeof(header32));
1089 T_FileStream_write(out, sectionHeaders32, (int32_t)sizeof(sectionHeaders32));
1090 T_FileStream_write(out, symbols32, (int32_t)sizeof(symbols32));
1091 } else /* bits==64 */ {
1093 header64.e_ident[EI_DATA]= makeBigEndian ? ELFDATA2MSB : ELFDATA2LSB;
1094 header64.e_machine=cpu;
1096 /* 16-align .rodata in the .o file, just in case */
1097 paddingSize=sectionHeaders64[4].sh_offset & 0xf;
1098 if(paddingSize!=0) {
1099 paddingSize=0x10-paddingSize;
1100 sectionHeaders64[4].sh_offset+=paddingSize;
1103 sectionHeaders64[4].sh_size=(Elf64_Xword)size;
1105 symbols64[1].st_size=(Elf64_Xword)size;
1107 /* write .o headers */
1108 T_FileStream_write(out, &header64, (int32_t)sizeof(header64));
1109 T_FileStream_write(out, sectionHeaders64, (int32_t)sizeof(sectionHeaders64));
1110 T_FileStream_write(out, symbols64, (int32_t)sizeof(symbols64));
1114 T_FileStream_write(out, sectionStrings, (int32_t)sizeof(sectionStrings));
1115 T_FileStream_write(out, entry, (int32_t)sizeof(entry));
1116 if(paddingSize!=0) {
1117 T_FileStream_write(out, padding, paddingSize);
1119 #elif U_PLATFORM_HAS_WIN32_API
1120 /* populate the .obj headers */
1121 uprv_memset(&objHeader, 0, sizeof(objHeader));
1122 uprv_memset(&symbols, 0, sizeof(symbols));
1123 uprv_memset(&symbolNames, 0, sizeof(symbolNames));
1125 /* write the linker export directive */
1126 uprv_strcpy(objHeader.linkerOptions, "-export:");
1128 uprv_strcpy(objHeader.linkerOptions+length, entry);
1129 length+=entryLength;
1130 uprv_strcpy(objHeader.linkerOptions+length, ",data ");
1133 /* set the file header */
1134 objHeader.fileHeader.Machine=cpu;
1135 objHeader.fileHeader.NumberOfSections=2;
1136 objHeader.fileHeader.TimeDateStamp=(DWORD)time(NULL);
1137 objHeader.fileHeader.PointerToSymbolTable=IMAGE_SIZEOF_FILE_HEADER+2*IMAGE_SIZEOF_SECTION_HEADER+length+size; /* start of symbol table */
1138 objHeader.fileHeader.NumberOfSymbols=1;
1140 /* set the section for the linker options */
1141 uprv_strncpy((char *)objHeader.sections[0].Name, ".drectve", 8);
1142 objHeader.sections[0].SizeOfRawData=length;
1143 objHeader.sections[0].PointerToRawData=IMAGE_SIZEOF_FILE_HEADER+2*IMAGE_SIZEOF_SECTION_HEADER;
1144 objHeader.sections[0].Characteristics=IMAGE_SCN_LNK_INFO|IMAGE_SCN_LNK_REMOVE|IMAGE_SCN_ALIGN_1BYTES;
1146 /* set the data section */
1147 uprv_strncpy((char *)objHeader.sections[1].Name, ".rdata", 6);
1148 objHeader.sections[1].SizeOfRawData=size;
1149 objHeader.sections[1].PointerToRawData=IMAGE_SIZEOF_FILE_HEADER+2*IMAGE_SIZEOF_SECTION_HEADER+length;
1150 objHeader.sections[1].Characteristics=IMAGE_SCN_CNT_INITIALIZED_DATA|IMAGE_SCN_ALIGN_16BYTES|IMAGE_SCN_MEM_READ;
1152 /* set the symbol table */
1153 if(entryLength<=8) {
1154 uprv_strncpy((char *)symbols[0].N.ShortName, entry, entryLength);
1155 symbolNames.sizeofLongNames=4;
1157 symbols[0].N.Name.Short=0;
1158 symbols[0].N.Name.Long=4;
1159 symbolNames.sizeofLongNames=4+entryLength+1;
1160 uprv_strcpy(symbolNames.longNames, entry);
1162 symbols[0].SectionNumber=2;
1163 symbols[0].StorageClass=IMAGE_SYM_CLASS_EXTERNAL;
1165 /* write the file header and the linker options section */
1166 T_FileStream_write(out, &objHeader, objHeader.sections[1].PointerToRawData);
1168 # error "Unknown platform for CAN_GENERATE_OBJECTS."
1171 /* copy the data file into section 2 */
1173 length=T_FileStream_read(in, buffer, sizeof(buffer));
1177 T_FileStream_write(out, buffer, (int32_t)length);
1180 #if U_PLATFORM_HAS_WIN32_API
1181 /* write the symbol table */
1182 T_FileStream_write(out, symbols, IMAGE_SIZEOF_SYMBOL);
1183 T_FileStream_write(out, &symbolNames, symbolNames.sizeofLongNames);
1186 if(T_FileStream_error(in)) {
1187 fprintf(stderr, "genccode: file read error while generating from file %s\n", filename);
1188 exit(U_FILE_ACCESS_ERROR);
1191 if(T_FileStream_error(out)) {
1192 fprintf(stderr, "genccode: file write error while generating from file %s\n", filename);
1193 exit(U_FILE_ACCESS_ERROR);
1196 T_FileStream_close(out);
1197 T_FileStream_close(in);