1 /******************************************************************************
2 * Copyright (C) 2009-2012, 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 */
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
[] = {
117 "\t.section .note.GNU-stack,\"\",%%progbits\n"
118 "\t.section .rodata\n"
119 "\t.align 8\n" /* Either align 8 bytes or 2^8 (256) bytes. 8 bytes is needed. */
120 "\t.type %s,%%object\n"
126 /*"\t.section __TEXT,__text,regular,pure_instructions\n"
127 "\t.section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32\n"*/
131 "\t.align 4\n" /* 1<<4 = 16 */
138 "\t.section .rodata\n"
139 "\t.align 8\n" /* Either align 8 bytes or 2^8 (256) bytes. 8 bytes is needed. */
146 "\t.section .rodata\n"
147 "\t.align 8\n" /* Either align 8 bytes or 2^8 (256) bytes. 8 bytes is needed. */
153 "\t.section \".rodata\"\n"
162 "\t.type Drodata.rodata,@object\n"
163 "\t.size Drodata.rodata,0\n"
174 "\t.csect %s{RO}, 4\n",
180 "\t.type %s,@object\n"
182 "\t.secalias .abe$0.rodata, \".rodata\"\n"
183 "\t.section .abe$0.rodata = \"a\", \"progbits\"\n"
200 "; generated by genccode\n"
204 "ICUDATA_%s\tSEGMENT READONLY PARA PUBLIC FLAT 'DATA'\n"
206 "_%s\tLABEL DWORD\n",
207 "\tDWORD ","\nICUDATA_%s\tENDS\n\tEND\n",HEX_0H
211 static int32_t assemblyHeaderIndex
= -1;
212 static int32_t hexType
= HEX_0X
;
214 U_CAPI UBool U_EXPORT2
215 checkAssemblyHeaderName(const char* optAssembly
) {
217 assemblyHeaderIndex
= -1;
218 for (idx
= 0; idx
< (int32_t)(sizeof(assemblyHeader
)/sizeof(assemblyHeader
[0])); idx
++) {
219 if (uprv_strcmp(optAssembly
, assemblyHeader
[idx
].name
) == 0) {
220 assemblyHeaderIndex
= idx
;
221 hexType
= assemblyHeader
[idx
].hexType
; /* set the hex type */
230 U_CAPI
void U_EXPORT2
231 printAssemblyHeadersToStdErr(void) {
233 fprintf(stderr
, "%s", assemblyHeader
[0].name
);
234 for (idx
= 1; idx
< (int32_t)(sizeof(assemblyHeader
)/sizeof(assemblyHeader
[0])); idx
++) {
235 fprintf(stderr
, ", %s", assemblyHeader
[idx
].name
);
241 U_CAPI
void U_EXPORT2
242 writeAssemblyCode(const char *filename
, const char *destdir
, const char *optEntryPoint
, const char *optFilename
, char *outFilePath
) {
243 uint32_t column
= MAX_COLUMN
;
245 uint32_t buffer
[1024];
246 char *bufferStr
= (char *)buffer
;
247 FileStream
*in
, *out
;
250 in
=T_FileStream_open(filename
, "rb");
252 fprintf(stderr
, "genccode: unable to open input file %s\n", filename
);
253 exit(U_FILE_ACCESS_ERROR
);
256 getOutFilename(filename
, destdir
, bufferStr
, entry
, ".s", optFilename
);
257 out
=T_FileStream_open(bufferStr
, "w");
259 fprintf(stderr
, "genccode: unable to open output file %s\n", bufferStr
);
260 exit(U_FILE_ACCESS_ERROR
);
263 if (outFilePath
!= NULL
) {
264 uprv_strcpy(outFilePath
, bufferStr
);
267 #ifdef WINDOWS_WITH_GNUC
268 /* Need to fix the file seperator character when using MinGW. */
269 swapFileSepChar(outFilePath
, U_FILE_SEP_CHAR
, '/');
272 if(optEntryPoint
!= NULL
) {
273 uprv_strcpy(entry
, optEntryPoint
);
274 uprv_strcat(entry
, "_dat");
277 /* turn dashes or dots in the entry name into underscores */
278 length
=uprv_strlen(entry
);
279 for(i
=0; i
<length
; ++i
) {
280 if(entry
[i
]=='-' || entry
[i
]=='.') {
285 sprintf(bufferStr
, assemblyHeader
[assemblyHeaderIndex
].header
,
286 entry
, entry
, entry
, entry
,
287 entry
, entry
, entry
, entry
);
288 T_FileStream_writeLine(out
, bufferStr
);
289 T_FileStream_writeLine(out
, assemblyHeader
[assemblyHeaderIndex
].beginLine
);
292 length
=T_FileStream_read(in
, buffer
, sizeof(buffer
));
296 if (length
!= sizeof(buffer
)) {
297 /* pad with extra 0's when at the end of the file */
298 for(i
=0; i
< (length
% sizeof(uint32_t)); ++i
) {
299 buffer
[length
+i
] = 0;
302 for(i
=0; i
<(length
/sizeof(buffer
[0])); i
++) {
303 column
= write32(out
, buffer
[i
], column
);
307 T_FileStream_writeLine(out
, "\n");
309 sprintf(bufferStr
, assemblyHeader
[assemblyHeaderIndex
].footer
,
310 entry
, entry
, entry
, entry
,
311 entry
, entry
, entry
, entry
);
312 T_FileStream_writeLine(out
, bufferStr
);
314 if(T_FileStream_error(in
)) {
315 fprintf(stderr
, "genccode: file read error while generating from file %s\n", filename
);
316 exit(U_FILE_ACCESS_ERROR
);
319 if(T_FileStream_error(out
)) {
320 fprintf(stderr
, "genccode: file write error while generating from file %s\n", filename
);
321 exit(U_FILE_ACCESS_ERROR
);
324 T_FileStream_close(out
);
325 T_FileStream_close(in
);
328 U_CAPI
void U_EXPORT2
329 writeCCode(const char *filename
, const char *destdir
, const char *optName
, const char *optFilename
, char *outFilePath
) {
330 uint32_t column
= MAX_COLUMN
;
331 char buffer
[4096], entry
[64];
332 FileStream
*in
, *out
;
335 in
=T_FileStream_open(filename
, "rb");
337 fprintf(stderr
, "genccode: unable to open input file %s\n", filename
);
338 exit(U_FILE_ACCESS_ERROR
);
341 if(optName
!= NULL
) { /* prepend 'icudt28_' */
342 strcpy(entry
, optName
);
348 getOutFilename(filename
, destdir
, buffer
, entry
+uprv_strlen(entry
), ".c", optFilename
);
349 if (outFilePath
!= NULL
) {
350 uprv_strcpy(outFilePath
, buffer
);
352 out
=T_FileStream_open(buffer
, "w");
354 fprintf(stderr
, "genccode: unable to open output file %s\n", buffer
);
355 exit(U_FILE_ACCESS_ERROR
);
358 /* turn dashes or dots in the entry name into underscores */
359 length
=uprv_strlen(entry
);
360 for(i
=0; i
<length
; ++i
) {
361 if(entry
[i
]=='-' || entry
[i
]=='.') {
366 #if U_PLATFORM == U_PF_OS400
368 TODO: Fix this once the compiler implements this feature. Keep in sync with udatamem.c
370 This is here because this platform can't currently put
371 const data into the read-only pages of an object or
372 shared library (service program). Only strings are allowed in read-only
373 pages, so we use char * strings to store the data.
375 In order to prevent the beginning of the data from ever matching the
376 magic numbers we must still use the initial double.
380 "#ifndef IN_GENERATED_CCODE\n"
381 "#define IN_GENERATED_CCODE\n"
382 "#define U_DISABLE_RENAMING 1\n"
383 "#include \"unicode/umachine.h\"\n"
388 " const char *bytes; \n"
391 T_FileStream_writeLine(out
, buffer
);
394 length
=T_FileStream_read(in
, buffer
, sizeof(buffer
));
398 for(i
=0; i
<length
; ++i
) {
399 column
= write8str(out
, (uint8_t)buffer
[i
], column
);
403 T_FileStream_writeLine(out
, "\"\n};\nU_CDECL_END\n");
405 /* Function renaming shouldn't be done in data */
407 "#ifndef IN_GENERATED_CCODE\n"
408 "#define IN_GENERATED_CCODE\n"
409 "#define U_DISABLE_RENAMING 1\n"
410 "#include \"unicode/umachine.h\"\n"
415 " uint8_t bytes[%ld]; \n"
417 (long)T_FileStream_size(in
), entry
);
418 T_FileStream_writeLine(out
, buffer
);
421 length
=T_FileStream_read(in
, buffer
, sizeof(buffer
));
425 for(i
=0; i
<length
; ++i
) {
426 column
= write8(out
, (uint8_t)buffer
[i
], column
);
430 T_FileStream_writeLine(out
, "\n}\n};\nU_CDECL_END\n");
433 if(T_FileStream_error(in
)) {
434 fprintf(stderr
, "genccode: file read error while generating from file %s\n", filename
);
435 exit(U_FILE_ACCESS_ERROR
);
438 if(T_FileStream_error(out
)) {
439 fprintf(stderr
, "genccode: file write error while generating from file %s\n", filename
);
440 exit(U_FILE_ACCESS_ERROR
);
443 T_FileStream_close(out
);
444 T_FileStream_close(in
);
448 write32(FileStream
*out
, uint32_t bitField
, uint32_t column
) {
450 char bitFieldStr
[64]; /* This is more bits than needed for a 32-bit number */
451 char *s
= bitFieldStr
;
452 uint8_t *ptrIdx
= (uint8_t *)&bitField
;
453 static const char hexToStr
[16] = {
460 /* write the value, possibly with comma and newline */
461 if(column
==MAX_COLUMN
) {
464 } else if(column
<32) {
469 uprv_strcpy(s
, assemblyHeader
[assemblyHeaderIndex
].beginLine
);
475 /* It's a small number. Don't waste the space for 0x */
476 *(s
++)=hexToStr
[bitField
];
479 int seenNonZero
= 0; /* This is used to remove leading zeros */
481 if(hexType
==HEX_0X
) {
484 } else if(hexType
==HEX_0H
) {
488 /* This creates a 32-bit field */
490 for (i
= 0; i
< sizeof(uint32_t); i
++)
492 for (i
= sizeof(uint32_t)-1; i
>= 0 ; i
--)
495 uint8_t value
= ptrIdx
[i
];
496 if (value
|| seenNonZero
) {
497 *(s
++)=hexToStr
[value
>>4];
498 *(s
++)=hexToStr
[value
&0xF];
502 if(hexType
==HEX_0H
) {
508 T_FileStream_writeLine(out
, bitFieldStr
);
513 write8(FileStream
*out
, uint8_t byte
, uint32_t column
) {
517 /* convert the byte value to a string */
519 s
[i
++]=(char)('0'+byte
/100);
522 if(i
>0 || byte
>=10) {
523 s
[i
++]=(char)('0'+byte
/10);
526 s
[i
++]=(char)('0'+byte
);
529 /* write the value, possibly with comma and newline */
530 if(column
==MAX_COLUMN
) {
533 } else if(column
<16) {
534 T_FileStream_writeLine(out
, ",");
537 T_FileStream_writeLine(out
, ",\n");
540 T_FileStream_writeLine(out
, s
);
544 #if U_PLATFORM == U_PF_OS400
546 write8str(FileStream
*out
, uint8_t byte
, uint32_t column
) {
550 sprintf(s
, "\\x%X", byte
);
552 sprintf(s
, "\\%X", byte
);
554 /* write the value, possibly with comma and newline */
555 if(column
==MAX_COLUMN
) {
558 T_FileStream_writeLine(out
, "\"");
559 } else if(column
<24) {
562 T_FileStream_writeLine(out
, "\"\n\"");
565 T_FileStream_writeLine(out
, s
);
571 getOutFilename(const char *inFilename
, const char *destdir
, char *outFilename
, char *entryName
, const char *newSuffix
, const char *optFilename
) {
572 const char *basename
=findBasename(inFilename
), *suffix
=uprv_strrchr(basename
, '.');
575 if(destdir
!=NULL
&& *destdir
!=0) {
577 *outFilename
++=*destdir
++;
578 } while(*destdir
!=0);
579 if(*(outFilename
-1)!=U_FILE_SEP_CHAR
) {
580 *outFilename
++=U_FILE_SEP_CHAR
;
584 while(inFilename
<basename
) {
585 *outFilename
++=*inFilename
++;
590 /* the filename does not have a suffix */
591 uprv_strcpy(entryName
, inFilename
);
592 if(optFilename
!= NULL
) {
593 uprv_strcpy(outFilename
, optFilename
);
595 uprv_strcpy(outFilename
, inFilename
);
597 uprv_strcat(outFilename
, newSuffix
);
599 char *saveOutFilename
= outFilename
;
601 while(inFilename
<suffix
) {
602 if(*inFilename
=='-') {
603 /* iSeries cannot have '-' in the .o objects. */
604 *outFilename
++=*entryName
++='_';
608 *outFilename
++=*entryName
++=*inFilename
++;
612 /* replace '.' by '_' */
613 *outFilename
++=*entryName
++='_';
617 while(*inFilename
!=0) {
618 *outFilename
++=*entryName
++=*inFilename
++;
623 if(optFilename
!= NULL
) {
624 uprv_strcpy(saveOutFilename
, optFilename
);
625 uprv_strcat(saveOutFilename
, newSuffix
);
628 uprv_strcpy(outFilename
, newSuffix
);
633 #ifdef CAN_GENERATE_OBJECTS
635 getArchitecture(uint16_t *pCPU
, uint16_t *pBits
, UBool
*pIsBigEndian
, const char *optMatchArch
) {
640 /* Elf32_Ehdr and ELF64_Ehdr are identical for the necessary fields. */
641 #elif U_PLATFORM_HAS_WIN32_API
642 IMAGE_FILE_HEADER header
;
646 const char *filename
;
652 #elif U_PLATFORM_HAS_WIN32_API
653 const IMAGE_FILE_HEADER
*pHeader
;
655 # error "Unknown platform for CAN_GENERATE_OBJECTS."
658 if(optMatchArch
!= NULL
) {
659 filename
=optMatchArch
;
663 /* set EM_386 because elf.h does not provide better defaults */
666 *pIsBigEndian
=(UBool
)(U_IS_BIG_ENDIAN
? ELFDATA2MSB
: ELFDATA2LSB
);
667 #elif U_PLATFORM_HAS_WIN32_API
668 /* _M_IA64 should be defined in windows.h */
669 # if defined(_M_IA64)
670 *pCPU
=IMAGE_FILE_MACHINE_IA64
;
671 # elif defined(_M_AMD64)
672 *pCPU
=IMAGE_FILE_MACHINE_AMD64
;
674 *pCPU
=IMAGE_FILE_MACHINE_I386
;
676 *pBits
= *pCPU
==IMAGE_FILE_MACHINE_I386
? 32 : 64;
679 # error "Unknown platform for CAN_GENERATE_OBJECTS."
684 in
=T_FileStream_open(filename
, "rb");
686 fprintf(stderr
, "genccode: unable to open match-arch file %s\n", filename
);
687 exit(U_FILE_ACCESS_ERROR
);
689 length
=T_FileStream_read(in
, buffer
.bytes
, sizeof(buffer
.bytes
));
692 if(length
<sizeof(Elf32_Ehdr
)) {
693 fprintf(stderr
, "genccode: match-arch file %s is too short\n", filename
);
694 exit(U_UNSUPPORTED_ERROR
);
697 buffer
.header32
.e_ident
[0]!=ELFMAG0
||
698 buffer
.header32
.e_ident
[1]!=ELFMAG1
||
699 buffer
.header32
.e_ident
[2]!=ELFMAG2
||
700 buffer
.header32
.e_ident
[3]!=ELFMAG3
||
701 buffer
.header32
.e_ident
[EI_CLASS
]<ELFCLASS32
|| buffer
.header32
.e_ident
[EI_CLASS
]>ELFCLASS64
703 fprintf(stderr
, "genccode: match-arch file %s is not an ELF object file, or not supported\n", filename
);
704 exit(U_UNSUPPORTED_ERROR
);
707 *pBits
= buffer
.header32
.e_ident
[EI_CLASS
]==ELFCLASS32
? 32 : 64; /* only 32 or 64: see check above */
709 if(*pBits
!=32 && *pBits
!=64) {
710 fprintf(stderr
, "genccode: currently only supports 32-bit and 64-bit ELF format\n");
711 exit(U_UNSUPPORTED_ERROR
);
715 fprintf(stderr
, "genccode: built with elf.h missing 64-bit definitions\n");
716 exit(U_UNSUPPORTED_ERROR
);
720 *pIsBigEndian
=(UBool
)(buffer
.header32
.e_ident
[EI_DATA
]==ELFDATA2MSB
);
721 if(*pIsBigEndian
!=U_IS_BIG_ENDIAN
) {
722 fprintf(stderr
, "genccode: currently only same-endianness ELF formats are supported\n");
723 exit(U_UNSUPPORTED_ERROR
);
725 /* TODO: Support byte swapping */
727 *pCPU
=buffer
.header32
.e_machine
;
728 #elif U_PLATFORM_HAS_WIN32_API
729 if(length
<sizeof(IMAGE_FILE_HEADER
)) {
730 fprintf(stderr
, "genccode: match-arch file %s is too short\n", filename
);
731 exit(U_UNSUPPORTED_ERROR
);
733 /* TODO: Use buffer.header. Keep aliasing legal. */
734 pHeader
=(const IMAGE_FILE_HEADER
*)buffer
.bytes
;
735 *pCPU
=pHeader
->Machine
;
737 * The number of bits is implicit with the Machine value.
738 * *pBits is ignored in the calling code, so this need not be precise.
740 *pBits
= *pCPU
==IMAGE_FILE_MACHINE_I386
? 32 : 64;
741 /* Windows always runs on little-endian CPUs. */
744 # error "Unknown platform for CAN_GENERATE_OBJECTS."
747 T_FileStream_close(in
);
750 U_CAPI
void U_EXPORT2
751 writeObjectCode(const char *filename
, const char *destdir
, const char *optEntryPoint
, const char *optMatchArch
, const char *optFilename
, char *outFilePath
) {
752 /* common variables */
753 char buffer
[4096], entry
[40]={ 0 };
754 FileStream
*in
, *out
;
755 const char *newSuffix
;
756 int32_t i
, entryLength
, length
, size
, entryOffset
=0, entryLengthOffset
=0;
761 /* platform-specific variables and initialization code */
763 /* 32-bit Elf file header */
764 static Elf32_Ehdr header32
={
767 ELFMAG0
, ELFMAG1
, ELFMAG2
, ELFMAG3
,
769 U_IS_BIG_ENDIAN
? ELFDATA2MSB
: ELFDATA2LSB
,
770 EV_CURRENT
/* EI_VERSION */
774 EV_CURRENT
, /* e_version */
777 (Elf32_Off
)sizeof(Elf32_Ehdr
), /* e_shoff */
779 (Elf32_Half
)sizeof(Elf32_Ehdr
), /* eh_size */
782 (Elf32_Half
)sizeof(Elf32_Shdr
), /* e_shentsize */
787 /* 32-bit Elf section header table */
788 static Elf32_Shdr sectionHeaders32
[5]={
797 (Elf32_Off
)(sizeof(header32
)+sizeof(sectionHeaders32
)), /* sh_offset */
798 (Elf32_Word
)(2*sizeof(Elf32_Sym
)), /* sh_size */
799 3, /* sh_link=sect hdr index of .strtab */
800 1, /* sh_info=One greater than the symbol table index of the last
801 * local symbol (with STB_LOCAL). */
802 4, /* sh_addralign */
803 (Elf32_Word
)(sizeof(Elf32_Sym
)) /* sh_entsize */
810 (Elf32_Off
)(sizeof(header32
)+sizeof(sectionHeaders32
)+2*sizeof(Elf32_Sym
)), /* sh_offset */
814 1, /* sh_addralign */
822 (Elf32_Off
)(sizeof(header32
)+sizeof(sectionHeaders32
)+2*sizeof(Elf32_Sym
)+40), /* sh_offset */
823 (Elf32_Word
)sizeof(entry
), /* sh_size */
826 1, /* sh_addralign */
832 SHF_ALLOC
, /* sh_flags */
834 (Elf32_Off
)(sizeof(header32
)+sizeof(sectionHeaders32
)+2*sizeof(Elf32_Sym
)+40+sizeof(entry
)), /* sh_offset */
838 16, /* sh_addralign */
844 static Elf32_Sym symbols32
[2]={
848 { /* data entry point */
852 ELF64_ST_INFO(STB_GLOBAL
, STT_OBJECT
),
854 4 /* st_shndx=index of related section table entry */
858 /* section header string table, with decimal string offsets */
859 static const char sectionStrings
[40]=
862 /* 9 */ ".shstrtab\0"
865 /* 35 */ "\0\0\0\0"; /* contains terminating NUL */
866 /* 40: padded to multiple of 8 bytes */
869 * Use entry[] for the string table which will contain only the
871 * entry[0] must be 0 (NUL)
872 * The entry point name can be up to 38 characters long (sizeof(entry)-2).
875 /* 16-align .rodata in the .o file, just in case */
876 static const char padding
[16]={ 0 };
880 /* 64-bit Elf file header */
881 static Elf64_Ehdr header64
={
884 ELFMAG0
, ELFMAG1
, ELFMAG2
, ELFMAG3
,
886 U_IS_BIG_ENDIAN
? ELFDATA2MSB
: ELFDATA2LSB
,
887 EV_CURRENT
/* EI_VERSION */
891 EV_CURRENT
, /* e_version */
894 (Elf64_Off
)sizeof(Elf64_Ehdr
), /* e_shoff */
896 (Elf64_Half
)sizeof(Elf64_Ehdr
), /* eh_size */
899 (Elf64_Half
)sizeof(Elf64_Shdr
), /* e_shentsize */
904 /* 64-bit Elf section header table */
905 static Elf64_Shdr sectionHeaders64
[5]={
914 (Elf64_Off
)(sizeof(header64
)+sizeof(sectionHeaders64
)), /* sh_offset */
915 (Elf64_Xword
)(2*sizeof(Elf64_Sym
)), /* sh_size */
916 3, /* sh_link=sect hdr index of .strtab */
917 1, /* sh_info=One greater than the symbol table index of the last
918 * local symbol (with STB_LOCAL). */
919 4, /* sh_addralign */
920 (Elf64_Xword
)(sizeof(Elf64_Sym
)) /* sh_entsize */
927 (Elf64_Off
)(sizeof(header64
)+sizeof(sectionHeaders64
)+2*sizeof(Elf64_Sym
)), /* sh_offset */
931 1, /* sh_addralign */
939 (Elf64_Off
)(sizeof(header64
)+sizeof(sectionHeaders64
)+2*sizeof(Elf64_Sym
)+40), /* sh_offset */
940 (Elf64_Xword
)sizeof(entry
), /* sh_size */
943 1, /* sh_addralign */
949 SHF_ALLOC
, /* sh_flags */
951 (Elf64_Off
)(sizeof(header64
)+sizeof(sectionHeaders64
)+2*sizeof(Elf64_Sym
)+40+sizeof(entry
)), /* sh_offset */
955 16, /* sh_addralign */
961 * 64-bit symbol table
962 * careful: different order of items compared with Elf32_sym!
964 static Elf64_Sym symbols64
[2]={
968 { /* data entry point */
970 ELF64_ST_INFO(STB_GLOBAL
, STT_OBJECT
),
972 4, /* st_shndx=index of related section table entry */
980 /* entry[] have a leading NUL */
983 /* in the common code, count entryLength from after the NUL */
988 #elif U_PLATFORM_HAS_WIN32_API
990 IMAGE_FILE_HEADER fileHeader
;
991 IMAGE_SECTION_HEADER sections
[2];
992 char linkerOptions
[100];
994 IMAGE_SYMBOL symbols
[1];
996 DWORD sizeofLongNames
;
1001 * entry sometimes have a leading '_'
1002 * overwritten if entryOffset==0 depending on the target platform
1003 * see check for cpu below
1009 # error "Unknown platform for CAN_GENERATE_OBJECTS."
1012 /* deal with options, files and the entry point name */
1013 getArchitecture(&cpu
, &bits
, &makeBigEndian
, optMatchArch
);
1014 printf("genccode: --match-arch cpu=%hu bits=%hu big-endian=%d\n", cpu
, bits
, makeBigEndian
);
1015 #if U_PLATFORM_HAS_WIN32_API
1016 if(cpu
==IMAGE_FILE_MACHINE_I386
) {
1021 in
=T_FileStream_open(filename
, "rb");
1023 fprintf(stderr
, "genccode: unable to open input file %s\n", filename
);
1024 exit(U_FILE_ACCESS_ERROR
);
1026 size
=T_FileStream_size(in
);
1028 getOutFilename(filename
, destdir
, buffer
, entry
+entryOffset
, newSuffix
, optFilename
);
1029 if (outFilePath
!= NULL
) {
1030 uprv_strcpy(outFilePath
, buffer
);
1033 if(optEntryPoint
!= NULL
) {
1034 uprv_strcpy(entry
+entryOffset
, optEntryPoint
);
1035 uprv_strcat(entry
+entryOffset
, "_dat");
1037 /* turn dashes in the entry name into underscores */
1038 entryLength
=(int32_t)uprv_strlen(entry
+entryLengthOffset
);
1039 for(i
=0; i
<entryLength
; ++i
) {
1040 if(entry
[entryLengthOffset
+i
]=='-') {
1041 entry
[entryLengthOffset
+i
]='_';
1045 /* open the output file */
1046 out
=T_FileStream_open(buffer
, "wb");
1048 fprintf(stderr
, "genccode: unable to open output file %s\n", buffer
);
1049 exit(U_FILE_ACCESS_ERROR
);
1054 header32
.e_ident
[EI_DATA
]= makeBigEndian
? ELFDATA2MSB
: ELFDATA2LSB
;
1055 header32
.e_machine
=cpu
;
1057 /* 16-align .rodata in the .o file, just in case */
1058 paddingSize
=sectionHeaders32
[4].sh_offset
& 0xf;
1059 if(paddingSize
!=0) {
1060 paddingSize
=0x10-paddingSize
;
1061 sectionHeaders32
[4].sh_offset
+=paddingSize
;
1064 sectionHeaders32
[4].sh_size
=(Elf32_Word
)size
;
1066 symbols32
[1].st_size
=(Elf32_Word
)size
;
1068 /* write .o headers */
1069 T_FileStream_write(out
, &header32
, (int32_t)sizeof(header32
));
1070 T_FileStream_write(out
, sectionHeaders32
, (int32_t)sizeof(sectionHeaders32
));
1071 T_FileStream_write(out
, symbols32
, (int32_t)sizeof(symbols32
));
1072 } else /* bits==64 */ {
1074 header64
.e_ident
[EI_DATA
]= makeBigEndian
? ELFDATA2MSB
: ELFDATA2LSB
;
1075 header64
.e_machine
=cpu
;
1077 /* 16-align .rodata in the .o file, just in case */
1078 paddingSize
=sectionHeaders64
[4].sh_offset
& 0xf;
1079 if(paddingSize
!=0) {
1080 paddingSize
=0x10-paddingSize
;
1081 sectionHeaders64
[4].sh_offset
+=paddingSize
;
1084 sectionHeaders64
[4].sh_size
=(Elf64_Xword
)size
;
1086 symbols64
[1].st_size
=(Elf64_Xword
)size
;
1088 /* write .o headers */
1089 T_FileStream_write(out
, &header64
, (int32_t)sizeof(header64
));
1090 T_FileStream_write(out
, sectionHeaders64
, (int32_t)sizeof(sectionHeaders64
));
1091 T_FileStream_write(out
, symbols64
, (int32_t)sizeof(symbols64
));
1095 T_FileStream_write(out
, sectionStrings
, (int32_t)sizeof(sectionStrings
));
1096 T_FileStream_write(out
, entry
, (int32_t)sizeof(entry
));
1097 if(paddingSize
!=0) {
1098 T_FileStream_write(out
, padding
, paddingSize
);
1100 #elif U_PLATFORM_HAS_WIN32_API
1101 /* populate the .obj headers */
1102 uprv_memset(&objHeader
, 0, sizeof(objHeader
));
1103 uprv_memset(&symbols
, 0, sizeof(symbols
));
1104 uprv_memset(&symbolNames
, 0, sizeof(symbolNames
));
1106 /* write the linker export directive */
1107 uprv_strcpy(objHeader
.linkerOptions
, "-export:");
1109 uprv_strcpy(objHeader
.linkerOptions
+length
, entry
);
1110 length
+=entryLength
;
1111 uprv_strcpy(objHeader
.linkerOptions
+length
, ",data ");
1114 /* set the file header */
1115 objHeader
.fileHeader
.Machine
=cpu
;
1116 objHeader
.fileHeader
.NumberOfSections
=2;
1117 objHeader
.fileHeader
.TimeDateStamp
=(DWORD
)time(NULL
);
1118 objHeader
.fileHeader
.PointerToSymbolTable
=IMAGE_SIZEOF_FILE_HEADER
+2*IMAGE_SIZEOF_SECTION_HEADER
+length
+size
; /* start of symbol table */
1119 objHeader
.fileHeader
.NumberOfSymbols
=1;
1121 /* set the section for the linker options */
1122 uprv_strncpy((char *)objHeader
.sections
[0].Name
, ".drectve", 8);
1123 objHeader
.sections
[0].SizeOfRawData
=length
;
1124 objHeader
.sections
[0].PointerToRawData
=IMAGE_SIZEOF_FILE_HEADER
+2*IMAGE_SIZEOF_SECTION_HEADER
;
1125 objHeader
.sections
[0].Characteristics
=IMAGE_SCN_LNK_INFO
|IMAGE_SCN_LNK_REMOVE
|IMAGE_SCN_ALIGN_1BYTES
;
1127 /* set the data section */
1128 uprv_strncpy((char *)objHeader
.sections
[1].Name
, ".rdata", 6);
1129 objHeader
.sections
[1].SizeOfRawData
=size
;
1130 objHeader
.sections
[1].PointerToRawData
=IMAGE_SIZEOF_FILE_HEADER
+2*IMAGE_SIZEOF_SECTION_HEADER
+length
;
1131 objHeader
.sections
[1].Characteristics
=IMAGE_SCN_CNT_INITIALIZED_DATA
|IMAGE_SCN_ALIGN_16BYTES
|IMAGE_SCN_MEM_READ
;
1133 /* set the symbol table */
1134 if(entryLength
<=8) {
1135 uprv_strncpy((char *)symbols
[0].N
.ShortName
, entry
, entryLength
);
1136 symbolNames
.sizeofLongNames
=4;
1138 symbols
[0].N
.Name
.Short
=0;
1139 symbols
[0].N
.Name
.Long
=4;
1140 symbolNames
.sizeofLongNames
=4+entryLength
+1;
1141 uprv_strcpy(symbolNames
.longNames
, entry
);
1143 symbols
[0].SectionNumber
=2;
1144 symbols
[0].StorageClass
=IMAGE_SYM_CLASS_EXTERNAL
;
1146 /* write the file header and the linker options section */
1147 T_FileStream_write(out
, &objHeader
, objHeader
.sections
[1].PointerToRawData
);
1149 # error "Unknown platform for CAN_GENERATE_OBJECTS."
1152 /* copy the data file into section 2 */
1154 length
=T_FileStream_read(in
, buffer
, sizeof(buffer
));
1158 T_FileStream_write(out
, buffer
, (int32_t)length
);
1161 #if U_PLATFORM_HAS_WIN32_API
1162 /* write the symbol table */
1163 T_FileStream_write(out
, symbols
, IMAGE_SIZEOF_SYMBOL
);
1164 T_FileStream_write(out
, &symbolNames
, symbolNames
.sizeofLongNames
);
1167 if(T_FileStream_error(in
)) {
1168 fprintf(stderr
, "genccode: file read error while generating from file %s\n", filename
);
1169 exit(U_FILE_ACCESS_ERROR
);
1172 if(T_FileStream_error(out
)) {
1173 fprintf(stderr
, "genccode: file write error while generating from file %s\n", filename
);
1174 exit(U_FILE_ACCESS_ERROR
);
1177 T_FileStream_close(out
);
1178 T_FileStream_close(in
);