1 /******************************************************************************
2 * Copyright (C) 2009-2011, 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
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 */
55 /* prototypes --------------------------------------------------------------- */
57 getOutFilename(const char *inFilename
, const char *destdir
, char *outFilename
, char *entryName
, const char *newSuffix
, const char *optFilename
);
60 write8(FileStream
*out
, uint8_t byte
, uint32_t column
);
63 write32(FileStream
*out
, uint32_t byte
, uint32_t column
);
65 #if U_PLATFORM == U_PF_OS400
67 write8str(FileStream
*out
, uint8_t byte
, uint32_t column
);
69 /* -------------------------------------------------------------------------- */
72 Creating Template Files for New Platforms
74 Let the cc compiler help you get started.
76 const unsigned int x[5] = {1, 2, 0xdeadbeef, 0xffffffff, 16};
77 with the -S option to produce assembly output.
79 For example, this will generate array.s:
82 This will produce a .s file that may look like this:
98 .ident "GCC: (GNU) 2.96 20000731 (Red Hat Linux 7.1 2.96-85)"
100 which gives a starting point that will compile, and can be transformed
101 to become the template, generally with some consulting of as docs and
102 some experimentation.
104 If you want ICU to automatically use this assembly, you should
105 specify "GENCCODE_ASSEMBLY=-a name" in the specific config/mh-* file,
106 where the name is the compiler or platform that you used in this
107 assemblyHeader data structure.
109 static const struct AssemblyType
{
112 const char *beginLine
;
114 int8_t hexType
; /* HEX_0X or HEX_0h */
115 } assemblyHeader
[] = {
118 "\t.section .note.GNU-stack,\"\",%%progbits\n"
119 "\t.section .rodata\n"
120 "\t.align 8\n" /* Either align 8 bytes or 2^8 (256) bytes. 8 bytes is needed. */
121 "\t.type %s,%%object\n"
127 /*"\t.section __TEXT,__text,regular,pure_instructions\n"
128 "\t.section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32\n"*/
132 "\t.align 4\n" /* 1<<4 = 16 */
139 "\t.section .rodata\n"
140 "\t.align 8\n" /* Either align 8 bytes or 2^8 (256) bytes. 8 bytes is needed. */
146 "\t.section \".rodata\"\n"
155 "\t.type Drodata.rodata,@object\n"
156 "\t.size Drodata.rodata,0\n"
167 "\t.csect %s{RO}, 4\n",
173 "\t.type %s,@object\n"
175 "\t.secalias .abe$0.rodata, \".rodata\"\n"
176 "\t.section .abe$0.rodata = \"a\", \"progbits\"\n"
193 "; generated by genccode\n"
197 "ICUDATA_%s\tSEGMENT READONLY PARA PUBLIC FLAT 'DATA'\n"
199 "_%s\tLABEL DWORD\n",
200 "\tDWORD ","\nICUDATA_%s\tENDS\n\tEND\n",HEX_0H
204 static int32_t assemblyHeaderIndex
= -1;
205 static int32_t hexType
= HEX_0X
;
207 U_CAPI UBool U_EXPORT2
208 checkAssemblyHeaderName(const char* optAssembly
) {
210 assemblyHeaderIndex
= -1;
211 for (idx
= 0; idx
< (int32_t)(sizeof(assemblyHeader
)/sizeof(assemblyHeader
[0])); idx
++) {
212 if (uprv_strcmp(optAssembly
, assemblyHeader
[idx
].name
) == 0) {
213 assemblyHeaderIndex
= idx
;
214 hexType
= assemblyHeader
[idx
].hexType
; /* set the hex type */
223 U_CAPI
void U_EXPORT2
224 printAssemblyHeadersToStdErr(void) {
226 fprintf(stderr
, "%s", assemblyHeader
[0].name
);
227 for (idx
= 1; idx
< (int32_t)(sizeof(assemblyHeader
)/sizeof(assemblyHeader
[0])); idx
++) {
228 fprintf(stderr
, ", %s", assemblyHeader
[idx
].name
);
234 U_CAPI
void U_EXPORT2
235 writeAssemblyCode(const char *filename
, const char *destdir
, const char *optEntryPoint
, const char *optFilename
, char *outFilePath
) {
236 uint32_t column
= MAX_COLUMN
;
238 uint32_t buffer
[1024];
239 char *bufferStr
= (char *)buffer
;
240 FileStream
*in
, *out
;
243 in
=T_FileStream_open(filename
, "rb");
245 fprintf(stderr
, "genccode: unable to open input file %s\n", filename
);
246 exit(U_FILE_ACCESS_ERROR
);
249 getOutFilename(filename
, destdir
, bufferStr
, entry
, ".s", optFilename
);
250 out
=T_FileStream_open(bufferStr
, "w");
252 fprintf(stderr
, "genccode: unable to open output file %s\n", bufferStr
);
253 exit(U_FILE_ACCESS_ERROR
);
256 if (outFilePath
!= NULL
) {
257 uprv_strcpy(outFilePath
, bufferStr
);
260 #ifdef WINDOWS_WITH_GNUC
261 /* Need to fix the file seperator character when using MinGW. */
262 swapFileSepChar(outFilePath
, U_FILE_SEP_CHAR
, '/');
265 if(optEntryPoint
!= NULL
) {
266 uprv_strcpy(entry
, optEntryPoint
);
267 uprv_strcat(entry
, "_dat");
270 /* turn dashes or dots in the entry name into underscores */
271 length
=uprv_strlen(entry
);
272 for(i
=0; i
<length
; ++i
) {
273 if(entry
[i
]=='-' || entry
[i
]=='.') {
278 sprintf(bufferStr
, assemblyHeader
[assemblyHeaderIndex
].header
,
279 entry
, entry
, entry
, entry
,
280 entry
, entry
, entry
, entry
);
281 T_FileStream_writeLine(out
, bufferStr
);
282 T_FileStream_writeLine(out
, assemblyHeader
[assemblyHeaderIndex
].beginLine
);
285 length
=T_FileStream_read(in
, buffer
, sizeof(buffer
));
289 if (length
!= sizeof(buffer
)) {
290 /* pad with extra 0's when at the end of the file */
291 for(i
=0; i
< (length
% sizeof(uint32_t)); ++i
) {
292 buffer
[length
+i
] = 0;
295 for(i
=0; i
<(length
/sizeof(buffer
[0])); i
++) {
296 column
= write32(out
, buffer
[i
], column
);
300 T_FileStream_writeLine(out
, "\n");
302 sprintf(bufferStr
, assemblyHeader
[assemblyHeaderIndex
].footer
,
303 entry
, entry
, entry
, entry
,
304 entry
, entry
, entry
, entry
);
305 T_FileStream_writeLine(out
, bufferStr
);
307 if(T_FileStream_error(in
)) {
308 fprintf(stderr
, "genccode: file read error while generating from file %s\n", filename
);
309 exit(U_FILE_ACCESS_ERROR
);
312 if(T_FileStream_error(out
)) {
313 fprintf(stderr
, "genccode: file write error while generating from file %s\n", filename
);
314 exit(U_FILE_ACCESS_ERROR
);
317 T_FileStream_close(out
);
318 T_FileStream_close(in
);
321 U_CAPI
void U_EXPORT2
322 writeCCode(const char *filename
, const char *destdir
, const char *optName
, const char *optFilename
, char *outFilePath
) {
323 uint32_t column
= MAX_COLUMN
;
324 char buffer
[4096], entry
[64];
325 FileStream
*in
, *out
;
328 in
=T_FileStream_open(filename
, "rb");
330 fprintf(stderr
, "genccode: unable to open input file %s\n", filename
);
331 exit(U_FILE_ACCESS_ERROR
);
334 if(optName
!= NULL
) { /* prepend 'icudt28_' */
335 strcpy(entry
, optName
);
341 getOutFilename(filename
, destdir
, buffer
, entry
+uprv_strlen(entry
), ".c", optFilename
);
342 if (outFilePath
!= NULL
) {
343 uprv_strcpy(outFilePath
, buffer
);
345 out
=T_FileStream_open(buffer
, "w");
347 fprintf(stderr
, "genccode: unable to open output file %s\n", buffer
);
348 exit(U_FILE_ACCESS_ERROR
);
351 /* turn dashes or dots in the entry name into underscores */
352 length
=uprv_strlen(entry
);
353 for(i
=0; i
<length
; ++i
) {
354 if(entry
[i
]=='-' || entry
[i
]=='.') {
359 #if U_PLATFORM == U_PF_OS400
361 TODO: Fix this once the compiler implements this feature. Keep in sync with udatamem.c
363 This is here because this platform can't currently put
364 const data into the read-only pages of an object or
365 shared library (service program). Only strings are allowed in read-only
366 pages, so we use char * strings to store the data.
368 In order to prevent the beginning of the data from ever matching the
369 magic numbers we must still use the initial double.
373 "#ifndef IN_GENERATED_CCODE\n"
374 "#define IN_GENERATED_CCODE\n"
375 "#define U_DISABLE_RENAMING 1\n"
376 "#include \"unicode/umachine.h\"\n"
381 " const char *bytes; \n"
384 T_FileStream_writeLine(out
, buffer
);
387 length
=T_FileStream_read(in
, buffer
, sizeof(buffer
));
391 for(i
=0; i
<length
; ++i
) {
392 column
= write8str(out
, (uint8_t)buffer
[i
], column
);
396 T_FileStream_writeLine(out
, "\"\n};\nU_CDECL_END\n");
398 /* Function renaming shouldn't be done in data */
400 "#ifndef IN_GENERATED_CCODE\n"
401 "#define IN_GENERATED_CCODE\n"
402 "#define U_DISABLE_RENAMING 1\n"
403 "#include \"unicode/umachine.h\"\n"
408 " uint8_t bytes[%ld]; \n"
410 (long)T_FileStream_size(in
), entry
);
411 T_FileStream_writeLine(out
, buffer
);
414 length
=T_FileStream_read(in
, buffer
, sizeof(buffer
));
418 for(i
=0; i
<length
; ++i
) {
419 column
= write8(out
, (uint8_t)buffer
[i
], column
);
423 T_FileStream_writeLine(out
, "\n}\n};\nU_CDECL_END\n");
426 if(T_FileStream_error(in
)) {
427 fprintf(stderr
, "genccode: file read error while generating from file %s\n", filename
);
428 exit(U_FILE_ACCESS_ERROR
);
431 if(T_FileStream_error(out
)) {
432 fprintf(stderr
, "genccode: file write error while generating from file %s\n", filename
);
433 exit(U_FILE_ACCESS_ERROR
);
436 T_FileStream_close(out
);
437 T_FileStream_close(in
);
441 write32(FileStream
*out
, uint32_t bitField
, uint32_t column
) {
443 char bitFieldStr
[64]; /* This is more bits than needed for a 32-bit number */
444 char *s
= bitFieldStr
;
445 uint8_t *ptrIdx
= (uint8_t *)&bitField
;
446 static const char hexToStr
[16] = {
453 /* write the value, possibly with comma and newline */
454 if(column
==MAX_COLUMN
) {
457 } else if(column
<32) {
462 uprv_strcpy(s
, assemblyHeader
[assemblyHeaderIndex
].beginLine
);
468 /* It's a small number. Don't waste the space for 0x */
469 *(s
++)=hexToStr
[bitField
];
472 int seenNonZero
= 0; /* This is used to remove leading zeros */
474 if(hexType
==HEX_0X
) {
477 } else if(hexType
==HEX_0H
) {
481 /* This creates a 32-bit field */
483 for (i
= 0; i
< sizeof(uint32_t); i
++)
485 for (i
= sizeof(uint32_t)-1; i
>= 0 ; i
--)
488 uint8_t value
= ptrIdx
[i
];
489 if (value
|| seenNonZero
) {
490 *(s
++)=hexToStr
[value
>>4];
491 *(s
++)=hexToStr
[value
&0xF];
495 if(hexType
==HEX_0H
) {
501 T_FileStream_writeLine(out
, bitFieldStr
);
506 write8(FileStream
*out
, uint8_t byte
, uint32_t column
) {
510 /* convert the byte value to a string */
512 s
[i
++]=(char)('0'+byte
/100);
515 if(i
>0 || byte
>=10) {
516 s
[i
++]=(char)('0'+byte
/10);
519 s
[i
++]=(char)('0'+byte
);
522 /* write the value, possibly with comma and newline */
523 if(column
==MAX_COLUMN
) {
526 } else if(column
<16) {
527 T_FileStream_writeLine(out
, ",");
530 T_FileStream_writeLine(out
, ",\n");
533 T_FileStream_writeLine(out
, s
);
537 #if U_PLATFORM == U_PF_OS400
539 write8str(FileStream
*out
, uint8_t byte
, uint32_t column
) {
543 sprintf(s
, "\\x%X", byte
);
545 sprintf(s
, "\\%X", byte
);
547 /* write the value, possibly with comma and newline */
548 if(column
==MAX_COLUMN
) {
551 T_FileStream_writeLine(out
, "\"");
552 } else if(column
<24) {
555 T_FileStream_writeLine(out
, "\"\n\"");
558 T_FileStream_writeLine(out
, s
);
564 getOutFilename(const char *inFilename
, const char *destdir
, char *outFilename
, char *entryName
, const char *newSuffix
, const char *optFilename
) {
565 const char *basename
=findBasename(inFilename
), *suffix
=uprv_strrchr(basename
, '.');
568 if(destdir
!=NULL
&& *destdir
!=0) {
570 *outFilename
++=*destdir
++;
571 } while(*destdir
!=0);
572 if(*(outFilename
-1)!=U_FILE_SEP_CHAR
) {
573 *outFilename
++=U_FILE_SEP_CHAR
;
577 while(inFilename
<basename
) {
578 *outFilename
++=*inFilename
++;
583 /* the filename does not have a suffix */
584 uprv_strcpy(entryName
, inFilename
);
585 if(optFilename
!= NULL
) {
586 uprv_strcpy(outFilename
, optFilename
);
588 uprv_strcpy(outFilename
, inFilename
);
590 uprv_strcat(outFilename
, newSuffix
);
592 char *saveOutFilename
= outFilename
;
594 while(inFilename
<suffix
) {
595 if(*inFilename
=='-') {
596 /* iSeries cannot have '-' in the .o objects. */
597 *outFilename
++=*entryName
++='_';
601 *outFilename
++=*entryName
++=*inFilename
++;
605 /* replace '.' by '_' */
606 *outFilename
++=*entryName
++='_';
610 while(*inFilename
!=0) {
611 *outFilename
++=*entryName
++=*inFilename
++;
616 if(optFilename
!= NULL
) {
617 uprv_strcpy(saveOutFilename
, optFilename
);
618 uprv_strcat(saveOutFilename
, newSuffix
);
621 uprv_strcpy(outFilename
, newSuffix
);
626 #ifdef CAN_GENERATE_OBJECTS
628 getArchitecture(uint16_t *pCPU
, uint16_t *pBits
, UBool
*pIsBigEndian
, const char *optMatchArch
) {
633 /* Elf32_Ehdr and ELF64_Ehdr are identical for the necessary fields. */
634 #elif U_PLATFORM_HAS_WIN32_API
635 IMAGE_FILE_HEADER header
;
639 const char *filename
;
645 #elif U_PLATFORM_HAS_WIN32_API
646 const IMAGE_FILE_HEADER
*pHeader
;
648 # error "Unknown platform for CAN_GENERATE_OBJECTS."
651 if(optMatchArch
!= NULL
) {
652 filename
=optMatchArch
;
656 /* set EM_386 because elf.h does not provide better defaults */
659 *pIsBigEndian
=(UBool
)(U_IS_BIG_ENDIAN
? ELFDATA2MSB
: ELFDATA2LSB
);
660 #elif U_PLATFORM_HAS_WIN32_API
661 /* _M_IA64 should be defined in windows.h */
662 # if defined(_M_IA64)
663 *pCPU
=IMAGE_FILE_MACHINE_IA64
;
664 # elif defined(_M_AMD64)
665 *pCPU
=IMAGE_FILE_MACHINE_AMD64
;
667 *pCPU
=IMAGE_FILE_MACHINE_I386
;
669 *pBits
= *pCPU
==IMAGE_FILE_MACHINE_I386
? 32 : 64;
672 # error "Unknown platform for CAN_GENERATE_OBJECTS."
677 in
=T_FileStream_open(filename
, "rb");
679 fprintf(stderr
, "genccode: unable to open match-arch file %s\n", filename
);
680 exit(U_FILE_ACCESS_ERROR
);
682 length
=T_FileStream_read(in
, buffer
.bytes
, sizeof(buffer
.bytes
));
685 if(length
<sizeof(Elf32_Ehdr
)) {
686 fprintf(stderr
, "genccode: match-arch file %s is too short\n", filename
);
687 exit(U_UNSUPPORTED_ERROR
);
690 buffer
.header32
.e_ident
[0]!=ELFMAG0
||
691 buffer
.header32
.e_ident
[1]!=ELFMAG1
||
692 buffer
.header32
.e_ident
[2]!=ELFMAG2
||
693 buffer
.header32
.e_ident
[3]!=ELFMAG3
||
694 buffer
.header32
.e_ident
[EI_CLASS
]<ELFCLASS32
|| buffer
.header32
.e_ident
[EI_CLASS
]>ELFCLASS64
696 fprintf(stderr
, "genccode: match-arch file %s is not an ELF object file, or not supported\n", filename
);
697 exit(U_UNSUPPORTED_ERROR
);
700 *pBits
= buffer
.header32
.e_ident
[EI_CLASS
]==ELFCLASS32
? 32 : 64; /* only 32 or 64: see check above */
702 if(*pBits
!=32 && *pBits
!=64) {
703 fprintf(stderr
, "genccode: currently only supports 32-bit and 64-bit ELF format\n");
704 exit(U_UNSUPPORTED_ERROR
);
708 fprintf(stderr
, "genccode: built with elf.h missing 64-bit definitions\n");
709 exit(U_UNSUPPORTED_ERROR
);
713 *pIsBigEndian
=(UBool
)(buffer
.header32
.e_ident
[EI_DATA
]==ELFDATA2MSB
);
714 if(*pIsBigEndian
!=U_IS_BIG_ENDIAN
) {
715 fprintf(stderr
, "genccode: currently only same-endianness ELF formats are supported\n");
716 exit(U_UNSUPPORTED_ERROR
);
718 /* TODO: Support byte swapping */
720 *pCPU
=buffer
.header32
.e_machine
;
721 #elif U_PLATFORM_HAS_WIN32_API
722 if(length
<sizeof(IMAGE_FILE_HEADER
)) {
723 fprintf(stderr
, "genccode: match-arch file %s is too short\n", filename
);
724 exit(U_UNSUPPORTED_ERROR
);
726 /* TODO: Use buffer.header. Keep aliasing legal. */
727 pHeader
=(const IMAGE_FILE_HEADER
*)buffer
.bytes
;
728 *pCPU
=pHeader
->Machine
;
730 * The number of bits is implicit with the Machine value.
731 * *pBits is ignored in the calling code, so this need not be precise.
733 *pBits
= *pCPU
==IMAGE_FILE_MACHINE_I386
? 32 : 64;
734 /* Windows always runs on little-endian CPUs. */
737 # error "Unknown platform for CAN_GENERATE_OBJECTS."
740 T_FileStream_close(in
);
743 U_CAPI
void U_EXPORT2
744 writeObjectCode(const char *filename
, const char *destdir
, const char *optEntryPoint
, const char *optMatchArch
, const char *optFilename
, char *outFilePath
) {
745 /* common variables */
746 char buffer
[4096], entry
[40]={ 0 };
747 FileStream
*in
, *out
;
748 const char *newSuffix
;
749 int32_t i
, entryLength
, length
, size
, entryOffset
=0, entryLengthOffset
=0;
754 /* platform-specific variables and initialization code */
756 /* 32-bit Elf file header */
757 static Elf32_Ehdr header32
={
760 ELFMAG0
, ELFMAG1
, ELFMAG2
, ELFMAG3
,
762 U_IS_BIG_ENDIAN
? ELFDATA2MSB
: ELFDATA2LSB
,
763 EV_CURRENT
/* EI_VERSION */
767 EV_CURRENT
, /* e_version */
770 (Elf32_Off
)sizeof(Elf32_Ehdr
), /* e_shoff */
772 (Elf32_Half
)sizeof(Elf32_Ehdr
), /* eh_size */
775 (Elf32_Half
)sizeof(Elf32_Shdr
), /* e_shentsize */
780 /* 32-bit Elf section header table */
781 static Elf32_Shdr sectionHeaders32
[5]={
790 (Elf32_Off
)(sizeof(header32
)+sizeof(sectionHeaders32
)), /* sh_offset */
791 (Elf32_Word
)(2*sizeof(Elf32_Sym
)), /* sh_size */
792 3, /* sh_link=sect hdr index of .strtab */
793 1, /* sh_info=One greater than the symbol table index of the last
794 * local symbol (with STB_LOCAL). */
795 4, /* sh_addralign */
796 (Elf32_Word
)(sizeof(Elf32_Sym
)) /* sh_entsize */
803 (Elf32_Off
)(sizeof(header32
)+sizeof(sectionHeaders32
)+2*sizeof(Elf32_Sym
)), /* sh_offset */
807 1, /* sh_addralign */
815 (Elf32_Off
)(sizeof(header32
)+sizeof(sectionHeaders32
)+2*sizeof(Elf32_Sym
)+40), /* sh_offset */
816 (Elf32_Word
)sizeof(entry
), /* sh_size */
819 1, /* sh_addralign */
825 SHF_ALLOC
, /* sh_flags */
827 (Elf32_Off
)(sizeof(header32
)+sizeof(sectionHeaders32
)+2*sizeof(Elf32_Sym
)+40+sizeof(entry
)), /* sh_offset */
831 16, /* sh_addralign */
837 static Elf32_Sym symbols32
[2]={
841 { /* data entry point */
845 ELF64_ST_INFO(STB_GLOBAL
, STT_OBJECT
),
847 4 /* st_shndx=index of related section table entry */
851 /* section header string table, with decimal string offsets */
852 static const char sectionStrings
[40]=
855 /* 9 */ ".shstrtab\0"
858 /* 35 */ "\0\0\0\0"; /* contains terminating NUL */
859 /* 40: padded to multiple of 8 bytes */
862 * Use entry[] for the string table which will contain only the
864 * entry[0] must be 0 (NUL)
865 * The entry point name can be up to 38 characters long (sizeof(entry)-2).
868 /* 16-align .rodata in the .o file, just in case */
869 static const char padding
[16]={ 0 };
873 /* 64-bit Elf file header */
874 static Elf64_Ehdr header64
={
877 ELFMAG0
, ELFMAG1
, ELFMAG2
, ELFMAG3
,
879 U_IS_BIG_ENDIAN
? ELFDATA2MSB
: ELFDATA2LSB
,
880 EV_CURRENT
/* EI_VERSION */
884 EV_CURRENT
, /* e_version */
887 (Elf64_Off
)sizeof(Elf64_Ehdr
), /* e_shoff */
889 (Elf64_Half
)sizeof(Elf64_Ehdr
), /* eh_size */
892 (Elf64_Half
)sizeof(Elf64_Shdr
), /* e_shentsize */
897 /* 64-bit Elf section header table */
898 static Elf64_Shdr sectionHeaders64
[5]={
907 (Elf64_Off
)(sizeof(header64
)+sizeof(sectionHeaders64
)), /* sh_offset */
908 (Elf64_Xword
)(2*sizeof(Elf64_Sym
)), /* sh_size */
909 3, /* sh_link=sect hdr index of .strtab */
910 1, /* sh_info=One greater than the symbol table index of the last
911 * local symbol (with STB_LOCAL). */
912 4, /* sh_addralign */
913 (Elf64_Xword
)(sizeof(Elf64_Sym
)) /* sh_entsize */
920 (Elf64_Off
)(sizeof(header64
)+sizeof(sectionHeaders64
)+2*sizeof(Elf64_Sym
)), /* sh_offset */
924 1, /* sh_addralign */
932 (Elf64_Off
)(sizeof(header64
)+sizeof(sectionHeaders64
)+2*sizeof(Elf64_Sym
)+40), /* sh_offset */
933 (Elf64_Xword
)sizeof(entry
), /* sh_size */
936 1, /* sh_addralign */
942 SHF_ALLOC
, /* sh_flags */
944 (Elf64_Off
)(sizeof(header64
)+sizeof(sectionHeaders64
)+2*sizeof(Elf64_Sym
)+40+sizeof(entry
)), /* sh_offset */
948 16, /* sh_addralign */
954 * 64-bit symbol table
955 * careful: different order of items compared with Elf32_sym!
957 static Elf64_Sym symbols64
[2]={
961 { /* data entry point */
963 ELF64_ST_INFO(STB_GLOBAL
, STT_OBJECT
),
965 4, /* st_shndx=index of related section table entry */
973 /* entry[] have a leading NUL */
976 /* in the common code, count entryLength from after the NUL */
981 #elif U_PLATFORM_HAS_WIN32_API
983 IMAGE_FILE_HEADER fileHeader
;
984 IMAGE_SECTION_HEADER sections
[2];
985 char linkerOptions
[100];
987 IMAGE_SYMBOL symbols
[1];
989 DWORD sizeofLongNames
;
994 * entry sometimes have a leading '_'
995 * overwritten if entryOffset==0 depending on the target platform
996 * see check for cpu below
1002 # error "Unknown platform for CAN_GENERATE_OBJECTS."
1005 /* deal with options, files and the entry point name */
1006 getArchitecture(&cpu
, &bits
, &makeBigEndian
, optMatchArch
);
1007 printf("genccode: --match-arch cpu=%hu bits=%hu big-endian=%hu\n", cpu
, bits
, makeBigEndian
);
1008 #if U_PLATFORM_HAS_WIN32_API
1009 if(cpu
==IMAGE_FILE_MACHINE_I386
) {
1014 in
=T_FileStream_open(filename
, "rb");
1016 fprintf(stderr
, "genccode: unable to open input file %s\n", filename
);
1017 exit(U_FILE_ACCESS_ERROR
);
1019 size
=T_FileStream_size(in
);
1021 getOutFilename(filename
, destdir
, buffer
, entry
+entryOffset
, newSuffix
, optFilename
);
1022 if (outFilePath
!= NULL
) {
1023 uprv_strcpy(outFilePath
, buffer
);
1026 if(optEntryPoint
!= NULL
) {
1027 uprv_strcpy(entry
+entryOffset
, optEntryPoint
);
1028 uprv_strcat(entry
+entryOffset
, "_dat");
1030 /* turn dashes in the entry name into underscores */
1031 entryLength
=(int32_t)uprv_strlen(entry
+entryLengthOffset
);
1032 for(i
=0; i
<entryLength
; ++i
) {
1033 if(entry
[entryLengthOffset
+i
]=='-') {
1034 entry
[entryLengthOffset
+i
]='_';
1038 /* open the output file */
1039 out
=T_FileStream_open(buffer
, "wb");
1041 fprintf(stderr
, "genccode: unable to open output file %s\n", buffer
);
1042 exit(U_FILE_ACCESS_ERROR
);
1047 header32
.e_ident
[EI_DATA
]= makeBigEndian
? ELFDATA2MSB
: ELFDATA2LSB
;
1048 header32
.e_machine
=cpu
;
1050 /* 16-align .rodata in the .o file, just in case */
1051 paddingSize
=sectionHeaders32
[4].sh_offset
& 0xf;
1052 if(paddingSize
!=0) {
1053 paddingSize
=0x10-paddingSize
;
1054 sectionHeaders32
[4].sh_offset
+=paddingSize
;
1057 sectionHeaders32
[4].sh_size
=(Elf32_Word
)size
;
1059 symbols32
[1].st_size
=(Elf32_Word
)size
;
1061 /* write .o headers */
1062 T_FileStream_write(out
, &header32
, (int32_t)sizeof(header32
));
1063 T_FileStream_write(out
, sectionHeaders32
, (int32_t)sizeof(sectionHeaders32
));
1064 T_FileStream_write(out
, symbols32
, (int32_t)sizeof(symbols32
));
1065 } else /* bits==64 */ {
1067 header64
.e_ident
[EI_DATA
]= makeBigEndian
? ELFDATA2MSB
: ELFDATA2LSB
;
1068 header64
.e_machine
=cpu
;
1070 /* 16-align .rodata in the .o file, just in case */
1071 paddingSize
=sectionHeaders64
[4].sh_offset
& 0xf;
1072 if(paddingSize
!=0) {
1073 paddingSize
=0x10-paddingSize
;
1074 sectionHeaders64
[4].sh_offset
+=paddingSize
;
1077 sectionHeaders64
[4].sh_size
=(Elf64_Xword
)size
;
1079 symbols64
[1].st_size
=(Elf64_Xword
)size
;
1081 /* write .o headers */
1082 T_FileStream_write(out
, &header64
, (int32_t)sizeof(header64
));
1083 T_FileStream_write(out
, sectionHeaders64
, (int32_t)sizeof(sectionHeaders64
));
1084 T_FileStream_write(out
, symbols64
, (int32_t)sizeof(symbols64
));
1088 T_FileStream_write(out
, sectionStrings
, (int32_t)sizeof(sectionStrings
));
1089 T_FileStream_write(out
, entry
, (int32_t)sizeof(entry
));
1090 if(paddingSize
!=0) {
1091 T_FileStream_write(out
, padding
, paddingSize
);
1093 #elif U_PLATFORM_HAS_WIN32_API
1094 /* populate the .obj headers */
1095 uprv_memset(&objHeader
, 0, sizeof(objHeader
));
1096 uprv_memset(&symbols
, 0, sizeof(symbols
));
1097 uprv_memset(&symbolNames
, 0, sizeof(symbolNames
));
1099 /* write the linker export directive */
1100 uprv_strcpy(objHeader
.linkerOptions
, "-export:");
1102 uprv_strcpy(objHeader
.linkerOptions
+length
, entry
);
1103 length
+=entryLength
;
1104 uprv_strcpy(objHeader
.linkerOptions
+length
, ",data ");
1107 /* set the file header */
1108 objHeader
.fileHeader
.Machine
=cpu
;
1109 objHeader
.fileHeader
.NumberOfSections
=2;
1110 objHeader
.fileHeader
.TimeDateStamp
=(DWORD
)time(NULL
);
1111 objHeader
.fileHeader
.PointerToSymbolTable
=IMAGE_SIZEOF_FILE_HEADER
+2*IMAGE_SIZEOF_SECTION_HEADER
+length
+size
; /* start of symbol table */
1112 objHeader
.fileHeader
.NumberOfSymbols
=1;
1114 /* set the section for the linker options */
1115 uprv_strncpy((char *)objHeader
.sections
[0].Name
, ".drectve", 8);
1116 objHeader
.sections
[0].SizeOfRawData
=length
;
1117 objHeader
.sections
[0].PointerToRawData
=IMAGE_SIZEOF_FILE_HEADER
+2*IMAGE_SIZEOF_SECTION_HEADER
;
1118 objHeader
.sections
[0].Characteristics
=IMAGE_SCN_LNK_INFO
|IMAGE_SCN_LNK_REMOVE
|IMAGE_SCN_ALIGN_1BYTES
;
1120 /* set the data section */
1121 uprv_strncpy((char *)objHeader
.sections
[1].Name
, ".rdata", 6);
1122 objHeader
.sections
[1].SizeOfRawData
=size
;
1123 objHeader
.sections
[1].PointerToRawData
=IMAGE_SIZEOF_FILE_HEADER
+2*IMAGE_SIZEOF_SECTION_HEADER
+length
;
1124 objHeader
.sections
[1].Characteristics
=IMAGE_SCN_CNT_INITIALIZED_DATA
|IMAGE_SCN_ALIGN_16BYTES
|IMAGE_SCN_MEM_READ
;
1126 /* set the symbol table */
1127 if(entryLength
<=8) {
1128 uprv_strncpy((char *)symbols
[0].N
.ShortName
, entry
, entryLength
);
1129 symbolNames
.sizeofLongNames
=4;
1131 symbols
[0].N
.Name
.Short
=0;
1132 symbols
[0].N
.Name
.Long
=4;
1133 symbolNames
.sizeofLongNames
=4+entryLength
+1;
1134 uprv_strcpy(symbolNames
.longNames
, entry
);
1136 symbols
[0].SectionNumber
=2;
1137 symbols
[0].StorageClass
=IMAGE_SYM_CLASS_EXTERNAL
;
1139 /* write the file header and the linker options section */
1140 T_FileStream_write(out
, &objHeader
, objHeader
.sections
[1].PointerToRawData
);
1142 # error "Unknown platform for CAN_GENERATE_OBJECTS."
1145 /* copy the data file into section 2 */
1147 length
=T_FileStream_read(in
, buffer
, sizeof(buffer
));
1151 T_FileStream_write(out
, buffer
, (int32_t)length
);
1154 #if U_PLATFORM_HAS_WIN32_API
1155 /* write the symbol table */
1156 T_FileStream_write(out
, symbols
, IMAGE_SIZEOF_SYMBOL
);
1157 T_FileStream_write(out
, &symbolNames
, symbolNames
.sizeofLongNames
);
1160 if(T_FileStream_error(in
)) {
1161 fprintf(stderr
, "genccode: file read error while generating from file %s\n", filename
);
1162 exit(U_FILE_ACCESS_ERROR
);
1165 if(T_FileStream_error(out
)) {
1166 fprintf(stderr
, "genccode: file write error while generating from file %s\n", filename
);
1167 exit(U_FILE_ACCESS_ERROR
);
1170 T_FileStream_close(out
);
1171 T_FileStream_close(in
);