1 /******************************************************************************
2 * Copyright (C) 2009-2010, International Business Machines
3 * Corporation and others. All Rights Reserved.
4 *******************************************************************************
6 #include "unicode/utypes.h"
10 # define WIN32_LEAN_AND_MEAN
18 # define WINDOWS_WITH_GNUC
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 #if defined(U_WINDOWS) || defined(U_ELF)
55 #define CAN_GENERATE_OBJECTS
58 /* prototypes --------------------------------------------------------------- */
60 getOutFilename(const char *inFilename
, const char *destdir
, char *outFilename
, char *entryName
, const char *newSuffix
, const char *optFilename
);
63 write8(FileStream
*out
, uint8_t byte
, uint32_t column
);
66 write32(FileStream
*out
, uint32_t byte
, uint32_t column
);
70 write8str(FileStream
*out
, uint8_t byte
, uint32_t column
);
72 /* -------------------------------------------------------------------------- */
75 Creating Template Files for New Platforms
77 Let the cc compiler help you get started.
79 const unsigned int x[5] = {1, 2, 0xdeadbeef, 0xffffffff, 16};
80 with the -S option to produce assembly output.
82 For example, this will generate array.s:
85 This will produce a .s file that may look like this:
101 .ident "GCC: (GNU) 2.96 20000731 (Red Hat Linux 7.1 2.96-85)"
103 which gives a starting point that will compile, and can be transformed
104 to become the template, generally with some consulting of as docs and
105 some experimentation.
107 If you want ICU to automatically use this assembly, you should
108 specify "GENCCODE_ASSEMBLY=-a name" in the specific config/mh-* file,
109 where the name is the compiler or platform that you used in this
110 assemblyHeader data structure.
112 static const struct AssemblyType
{
115 const char *beginLine
;
117 int8_t hexType
; /* HEX_0X or HEX_0h */
118 } assemblyHeader
[] = {
121 "\t.section .note.GNU-stack,\"\",%%progbits\n"
122 "\t.section .rodata\n"
123 "\t.align 8\n" /* Either align 8 bytes or 2^8 (256) bytes. 8 bytes is needed. */
124 "\t.type %s,%%object\n"
130 /*"\t.section __TEXT,__text,regular,pure_instructions\n"
131 "\t.section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32\n"*/
135 "\t.align 4\n" /* 1<<4 = 16 */
142 "\t.section .rodata\n"
143 "\t.align 8\n" /* Either align 8 bytes or 2^8 (256) bytes. 8 bytes is needed. */
149 "\t.section \".rodata\"\n"
158 "\t.type Drodata.rodata,@object\n"
159 "\t.size Drodata.rodata,0\n"
170 "\t.csect %s{RO}, 4\n",
176 "\t.type %s,@object\n"
178 "\t.secalias .abe$0.rodata, \".rodata\"\n"
179 "\t.section .abe$0.rodata = \"a\", \"progbits\"\n"
196 "; generated by genccode\n"
200 "ICUDATA_%s\tSEGMENT READONLY PARA PUBLIC FLAT 'DATA'\n"
202 "_%s\tLABEL DWORD\n",
203 "\tDWORD ","\nICUDATA_%s\tENDS\n\tEND\n",HEX_0H
207 static int32_t assemblyHeaderIndex
= -1;
208 static int32_t hexType
= HEX_0X
;
210 U_CAPI UBool U_EXPORT2
211 checkAssemblyHeaderName(const char* optAssembly
) {
213 assemblyHeaderIndex
= -1;
214 for (idx
= 0; idx
< (int32_t)(sizeof(assemblyHeader
)/sizeof(assemblyHeader
[0])); idx
++) {
215 if (uprv_strcmp(optAssembly
, assemblyHeader
[idx
].name
) == 0) {
216 assemblyHeaderIndex
= idx
;
217 hexType
= assemblyHeader
[idx
].hexType
; /* set the hex type */
226 U_CAPI
void U_EXPORT2
227 printAssemblyHeadersToStdErr(void) {
229 fprintf(stderr
, "%s", assemblyHeader
[0].name
);
230 for (idx
= 1; idx
< (int32_t)(sizeof(assemblyHeader
)/sizeof(assemblyHeader
[0])); idx
++) {
231 fprintf(stderr
, ", %s", assemblyHeader
[idx
].name
);
237 U_CAPI
void U_EXPORT2
238 writeAssemblyCode(const char *filename
, const char *destdir
, const char *optEntryPoint
, const char *optFilename
, char *outFilePath
) {
239 uint32_t column
= MAX_COLUMN
;
241 uint32_t buffer
[1024];
242 char *bufferStr
= (char *)buffer
;
243 FileStream
*in
, *out
;
246 in
=T_FileStream_open(filename
, "rb");
248 fprintf(stderr
, "genccode: unable to open input file %s\n", filename
);
249 exit(U_FILE_ACCESS_ERROR
);
252 getOutFilename(filename
, destdir
, bufferStr
, entry
, ".s", optFilename
);
253 out
=T_FileStream_open(bufferStr
, "w");
255 fprintf(stderr
, "genccode: unable to open output file %s\n", bufferStr
);
256 exit(U_FILE_ACCESS_ERROR
);
259 if (outFilePath
!= NULL
) {
260 uprv_strcpy(outFilePath
, bufferStr
);
263 #ifdef WINDOWS_WITH_GNUC
264 /* Need to fix the file seperator character when using MinGW. */
265 swapFileSepChar(outFilePath
, U_FILE_SEP_CHAR
, '/');
268 if(optEntryPoint
!= NULL
) {
269 uprv_strcpy(entry
, optEntryPoint
);
270 uprv_strcat(entry
, "_dat");
273 /* turn dashes or dots in the entry name into underscores */
274 length
=uprv_strlen(entry
);
275 for(i
=0; i
<length
; ++i
) {
276 if(entry
[i
]=='-' || entry
[i
]=='.') {
281 sprintf(bufferStr
, assemblyHeader
[assemblyHeaderIndex
].header
,
282 entry
, entry
, entry
, entry
,
283 entry
, entry
, entry
, entry
);
284 T_FileStream_writeLine(out
, bufferStr
);
285 T_FileStream_writeLine(out
, assemblyHeader
[assemblyHeaderIndex
].beginLine
);
288 length
=T_FileStream_read(in
, buffer
, sizeof(buffer
));
292 if (length
!= sizeof(buffer
)) {
293 /* pad with extra 0's when at the end of the file */
294 for(i
=0; i
< (length
% sizeof(uint32_t)); ++i
) {
295 buffer
[length
+i
] = 0;
298 for(i
=0; i
<(length
/sizeof(buffer
[0])); i
++) {
299 column
= write32(out
, buffer
[i
], column
);
303 T_FileStream_writeLine(out
, "\n");
305 sprintf(bufferStr
, assemblyHeader
[assemblyHeaderIndex
].footer
,
306 entry
, entry
, entry
, entry
,
307 entry
, entry
, entry
, entry
);
308 T_FileStream_writeLine(out
, bufferStr
);
310 if(T_FileStream_error(in
)) {
311 fprintf(stderr
, "genccode: file read error while generating from file %s\n", filename
);
312 exit(U_FILE_ACCESS_ERROR
);
315 if(T_FileStream_error(out
)) {
316 fprintf(stderr
, "genccode: file write error while generating from file %s\n", filename
);
317 exit(U_FILE_ACCESS_ERROR
);
320 T_FileStream_close(out
);
321 T_FileStream_close(in
);
324 U_CAPI
void U_EXPORT2
325 writeCCode(const char *filename
, const char *destdir
, const char *optName
, const char *optFilename
, char *outFilePath
) {
326 uint32_t column
= MAX_COLUMN
;
327 char buffer
[4096], entry
[64];
328 FileStream
*in
, *out
;
331 in
=T_FileStream_open(filename
, "rb");
333 fprintf(stderr
, "genccode: unable to open input file %s\n", filename
);
334 exit(U_FILE_ACCESS_ERROR
);
337 if(optName
!= NULL
) { /* prepend 'icudt28_' */
338 strcpy(entry
, optName
);
344 getOutFilename(filename
, destdir
, buffer
, entry
+uprv_strlen(entry
), ".c", optFilename
);
345 if (outFilePath
!= NULL
) {
346 uprv_strcpy(outFilePath
, buffer
);
348 out
=T_FileStream_open(buffer
, "w");
350 fprintf(stderr
, "genccode: unable to open output file %s\n", buffer
);
351 exit(U_FILE_ACCESS_ERROR
);
354 /* turn dashes or dots in the entry name into underscores */
355 length
=uprv_strlen(entry
);
356 for(i
=0; i
<length
; ++i
) {
357 if(entry
[i
]=='-' || entry
[i
]=='.') {
364 TODO: Fix this once the compiler implements this feature. Keep in sync with udatamem.c
366 This is here because this platform can't currently put
367 const data into the read-only pages of an object or
368 shared library (service program). Only strings are allowed in read-only
369 pages, so we use char * strings to store the data.
371 In order to prevent the beginning of the data from ever matching the
372 magic numbers we must still use the initial double.
376 "#define U_DISABLE_RENAMING 1\n"
377 "#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 "#define U_DISABLE_RENAMING 1\n"
401 "#include \"unicode/umachine.h\"\n"
405 " uint8_t bytes[%ld]; \n"
407 (long)T_FileStream_size(in
), entry
);
408 T_FileStream_writeLine(out
, buffer
);
411 length
=T_FileStream_read(in
, buffer
, sizeof(buffer
));
415 for(i
=0; i
<length
; ++i
) {
416 column
= write8(out
, (uint8_t)buffer
[i
], column
);
420 T_FileStream_writeLine(out
, "\n}\n};\nU_CDECL_END\n");
423 if(T_FileStream_error(in
)) {
424 fprintf(stderr
, "genccode: file read error while generating from file %s\n", filename
);
425 exit(U_FILE_ACCESS_ERROR
);
428 if(T_FileStream_error(out
)) {
429 fprintf(stderr
, "genccode: file write error while generating from file %s\n", filename
);
430 exit(U_FILE_ACCESS_ERROR
);
433 T_FileStream_close(out
);
434 T_FileStream_close(in
);
438 write32(FileStream
*out
, uint32_t bitField
, uint32_t column
) {
440 char bitFieldStr
[64]; /* This is more bits than needed for a 32-bit number */
441 char *s
= bitFieldStr
;
442 uint8_t *ptrIdx
= (uint8_t *)&bitField
;
443 static const char hexToStr
[16] = {
450 /* write the value, possibly with comma and newline */
451 if(column
==MAX_COLUMN
) {
454 } else if(column
<32) {
459 uprv_strcpy(s
, assemblyHeader
[assemblyHeaderIndex
].beginLine
);
465 /* It's a small number. Don't waste the space for 0x */
466 *(s
++)=hexToStr
[bitField
];
469 int seenNonZero
= 0; /* This is used to remove leading zeros */
471 if(hexType
==HEX_0X
) {
474 } else if(hexType
==HEX_0H
) {
478 /* This creates a 32-bit field */
480 for (i
= 0; i
< sizeof(uint32_t); i
++)
482 for (i
= sizeof(uint32_t)-1; i
>= 0 ; i
--)
485 uint8_t value
= ptrIdx
[i
];
486 if (value
|| seenNonZero
) {
487 *(s
++)=hexToStr
[value
>>4];
488 *(s
++)=hexToStr
[value
&0xF];
492 if(hexType
==HEX_0H
) {
498 T_FileStream_writeLine(out
, bitFieldStr
);
503 write8(FileStream
*out
, uint8_t byte
, uint32_t column
) {
507 /* convert the byte value to a string */
509 s
[i
++]=(char)('0'+byte
/100);
512 if(i
>0 || byte
>=10) {
513 s
[i
++]=(char)('0'+byte
/10);
516 s
[i
++]=(char)('0'+byte
);
519 /* write the value, possibly with comma and newline */
520 if(column
==MAX_COLUMN
) {
523 } else if(column
<16) {
524 T_FileStream_writeLine(out
, ",");
527 T_FileStream_writeLine(out
, ",\n");
530 T_FileStream_writeLine(out
, s
);
536 write8str(FileStream
*out
, uint8_t byte
, uint32_t column
) {
540 sprintf(s
, "\\x%X", byte
);
542 sprintf(s
, "\\%X", byte
);
544 /* write the value, possibly with comma and newline */
545 if(column
==MAX_COLUMN
) {
548 T_FileStream_writeLine(out
, "\"");
549 } else if(column
<24) {
552 T_FileStream_writeLine(out
, "\"\n\"");
555 T_FileStream_writeLine(out
, s
);
561 getOutFilename(const char *inFilename
, const char *destdir
, char *outFilename
, char *entryName
, const char *newSuffix
, const char *optFilename
) {
562 const char *basename
=findBasename(inFilename
), *suffix
=uprv_strrchr(basename
, '.');
565 if(destdir
!=NULL
&& *destdir
!=0) {
567 *outFilename
++=*destdir
++;
568 } while(*destdir
!=0);
569 if(*(outFilename
-1)!=U_FILE_SEP_CHAR
) {
570 *outFilename
++=U_FILE_SEP_CHAR
;
574 while(inFilename
<basename
) {
575 *outFilename
++=*inFilename
++;
580 /* the filename does not have a suffix */
581 uprv_strcpy(entryName
, inFilename
);
582 if(optFilename
!= NULL
) {
583 uprv_strcpy(outFilename
, optFilename
);
585 uprv_strcpy(outFilename
, inFilename
);
587 uprv_strcat(outFilename
, newSuffix
);
589 char *saveOutFilename
= outFilename
;
591 while(inFilename
<suffix
) {
592 if(*inFilename
=='-') {
593 /* iSeries cannot have '-' in the .o objects. */
594 *outFilename
++=*entryName
++='_';
598 *outFilename
++=*entryName
++=*inFilename
++;
602 /* replace '.' by '_' */
603 *outFilename
++=*entryName
++='_';
607 while(*inFilename
!=0) {
608 *outFilename
++=*entryName
++=*inFilename
++;
613 if(optFilename
!= NULL
) {
614 uprv_strcpy(saveOutFilename
, optFilename
);
615 uprv_strcat(saveOutFilename
, newSuffix
);
618 uprv_strcpy(outFilename
, newSuffix
);
623 #ifdef CAN_GENERATE_OBJECTS
625 getArchitecture(uint16_t *pCPU
, uint16_t *pBits
, UBool
*pIsBigEndian
, const char *optMatchArch
) {
630 /* Elf32_Ehdr and ELF64_Ehdr are identical for the necessary fields. */
631 #elif defined(U_WINDOWS)
632 IMAGE_FILE_HEADER header
;
636 const char *filename
;
642 #elif defined(U_WINDOWS)
643 const IMAGE_FILE_HEADER
*pHeader
;
645 # error "Unknown platform for CAN_GENERATE_OBJECTS."
648 if(optMatchArch
!= NULL
) {
649 filename
=optMatchArch
;
653 /* set EM_386 because elf.h does not provide better defaults */
656 *pIsBigEndian
=(UBool
)(U_IS_BIG_ENDIAN
? ELFDATA2MSB
: ELFDATA2LSB
);
657 #elif defined(U_WINDOWS)
658 /* _M_IA64 should be defined in windows.h */
659 # if defined(_M_IA64)
660 *pCPU
=IMAGE_FILE_MACHINE_IA64
;
661 # elif defined(_M_AMD64)
662 *pCPU
=IMAGE_FILE_MACHINE_AMD64
;
664 *pCPU
=IMAGE_FILE_MACHINE_I386
;
666 *pBits
= *pCPU
==IMAGE_FILE_MACHINE_I386
? 32 : 64;
669 # error "Unknown platform for CAN_GENERATE_OBJECTS."
674 in
=T_FileStream_open(filename
, "rb");
676 fprintf(stderr
, "genccode: unable to open match-arch file %s\n", filename
);
677 exit(U_FILE_ACCESS_ERROR
);
679 length
=T_FileStream_read(in
, buffer
.bytes
, sizeof(buffer
.bytes
));
682 if(length
<sizeof(Elf32_Ehdr
)) {
683 fprintf(stderr
, "genccode: match-arch file %s is too short\n", filename
);
684 exit(U_UNSUPPORTED_ERROR
);
687 buffer
.header32
.e_ident
[0]!=ELFMAG0
||
688 buffer
.header32
.e_ident
[1]!=ELFMAG1
||
689 buffer
.header32
.e_ident
[2]!=ELFMAG2
||
690 buffer
.header32
.e_ident
[3]!=ELFMAG3
||
691 buffer
.header32
.e_ident
[EI_CLASS
]<ELFCLASS32
|| buffer
.header32
.e_ident
[EI_CLASS
]>ELFCLASS64
693 fprintf(stderr
, "genccode: match-arch file %s is not an ELF object file, or not supported\n", filename
);
694 exit(U_UNSUPPORTED_ERROR
);
697 *pBits
= buffer
.header32
.e_ident
[EI_CLASS
]==ELFCLASS32
? 32 : 64; /* only 32 or 64: see check above */
699 if(*pBits
!=32 && *pBits
!=64) {
700 fprintf(stderr
, "genccode: currently only supports 32-bit and 64-bit ELF format\n");
701 exit(U_UNSUPPORTED_ERROR
);
705 fprintf(stderr
, "genccode: built with elf.h missing 64-bit definitions\n");
706 exit(U_UNSUPPORTED_ERROR
);
710 *pIsBigEndian
=(UBool
)(buffer
.header32
.e_ident
[EI_DATA
]==ELFDATA2MSB
);
711 if(*pIsBigEndian
!=U_IS_BIG_ENDIAN
) {
712 fprintf(stderr
, "genccode: currently only same-endianness ELF formats are supported\n");
713 exit(U_UNSUPPORTED_ERROR
);
715 /* TODO: Support byte swapping */
717 *pCPU
=buffer
.header32
.e_machine
;
718 #elif defined(U_WINDOWS)
719 if(length
<sizeof(IMAGE_FILE_HEADER
)) {
720 fprintf(stderr
, "genccode: match-arch file %s is too short\n", filename
);
721 exit(U_UNSUPPORTED_ERROR
);
723 /* TODO: Use buffer.header. Keep aliasing legal. */
724 pHeader
=(const IMAGE_FILE_HEADER
*)buffer
.bytes
;
725 *pCPU
=pHeader
->Machine
;
727 * The number of bits is implicit with the Machine value.
728 * *pBits is ignored in the calling code, so this need not be precise.
730 *pBits
= *pCPU
==IMAGE_FILE_MACHINE_I386
? 32 : 64;
731 /* Windows always runs on little-endian CPUs. */
734 # error "Unknown platform for CAN_GENERATE_OBJECTS."
737 T_FileStream_close(in
);
740 U_CAPI
void U_EXPORT2
741 writeObjectCode(const char *filename
, const char *destdir
, const char *optEntryPoint
, const char *optMatchArch
, const char *optFilename
, char *outFilePath
) {
742 /* common variables */
743 char buffer
[4096], entry
[40]={ 0 };
744 FileStream
*in
, *out
;
745 const char *newSuffix
;
746 int32_t i
, entryLength
, length
, size
, entryOffset
=0, entryLengthOffset
=0;
751 /* platform-specific variables and initialization code */
753 /* 32-bit Elf file header */
754 static Elf32_Ehdr header32
={
757 ELFMAG0
, ELFMAG1
, ELFMAG2
, ELFMAG3
,
759 U_IS_BIG_ENDIAN
? ELFDATA2MSB
: ELFDATA2LSB
,
760 EV_CURRENT
/* EI_VERSION */
764 EV_CURRENT
, /* e_version */
767 (Elf32_Off
)sizeof(Elf32_Ehdr
), /* e_shoff */
769 (Elf32_Half
)sizeof(Elf32_Ehdr
), /* eh_size */
772 (Elf32_Half
)sizeof(Elf32_Shdr
), /* e_shentsize */
777 /* 32-bit Elf section header table */
778 static Elf32_Shdr sectionHeaders32
[5]={
787 (Elf32_Off
)(sizeof(header32
)+sizeof(sectionHeaders32
)), /* sh_offset */
788 (Elf32_Word
)(2*sizeof(Elf32_Sym
)), /* sh_size */
789 3, /* sh_link=sect hdr index of .strtab */
790 1, /* sh_info=One greater than the symbol table index of the last
791 * local symbol (with STB_LOCAL). */
792 4, /* sh_addralign */
793 (Elf32_Word
)(sizeof(Elf32_Sym
)) /* sh_entsize */
800 (Elf32_Off
)(sizeof(header32
)+sizeof(sectionHeaders32
)+2*sizeof(Elf32_Sym
)), /* sh_offset */
804 1, /* sh_addralign */
812 (Elf32_Off
)(sizeof(header32
)+sizeof(sectionHeaders32
)+2*sizeof(Elf32_Sym
)+40), /* sh_offset */
813 (Elf32_Word
)sizeof(entry
), /* sh_size */
816 1, /* sh_addralign */
822 SHF_ALLOC
, /* sh_flags */
824 (Elf32_Off
)(sizeof(header32
)+sizeof(sectionHeaders32
)+2*sizeof(Elf32_Sym
)+40+sizeof(entry
)), /* sh_offset */
828 16, /* sh_addralign */
834 static Elf32_Sym symbols32
[2]={
838 { /* data entry point */
842 ELF64_ST_INFO(STB_GLOBAL
, STT_OBJECT
),
844 4 /* st_shndx=index of related section table entry */
848 /* section header string table, with decimal string offsets */
849 static const char sectionStrings
[40]=
852 /* 9 */ ".shstrtab\0"
855 /* 35 */ "\0\0\0\0"; /* contains terminating NUL */
856 /* 40: padded to multiple of 8 bytes */
859 * Use entry[] for the string table which will contain only the
861 * entry[0] must be 0 (NUL)
862 * The entry point name can be up to 38 characters long (sizeof(entry)-2).
865 /* 16-align .rodata in the .o file, just in case */
866 static const char padding
[16]={ 0 };
870 /* 64-bit Elf file header */
871 static Elf64_Ehdr header64
={
874 ELFMAG0
, ELFMAG1
, ELFMAG2
, ELFMAG3
,
876 U_IS_BIG_ENDIAN
? ELFDATA2MSB
: ELFDATA2LSB
,
877 EV_CURRENT
/* EI_VERSION */
881 EV_CURRENT
, /* e_version */
884 (Elf64_Off
)sizeof(Elf64_Ehdr
), /* e_shoff */
886 (Elf64_Half
)sizeof(Elf64_Ehdr
), /* eh_size */
889 (Elf64_Half
)sizeof(Elf64_Shdr
), /* e_shentsize */
894 /* 64-bit Elf section header table */
895 static Elf64_Shdr sectionHeaders64
[5]={
904 (Elf64_Off
)(sizeof(header64
)+sizeof(sectionHeaders64
)), /* sh_offset */
905 (Elf64_Xword
)(2*sizeof(Elf64_Sym
)), /* sh_size */
906 3, /* sh_link=sect hdr index of .strtab */
907 1, /* sh_info=One greater than the symbol table index of the last
908 * local symbol (with STB_LOCAL). */
909 4, /* sh_addralign */
910 (Elf64_Xword
)(sizeof(Elf64_Sym
)) /* sh_entsize */
917 (Elf64_Off
)(sizeof(header64
)+sizeof(sectionHeaders64
)+2*sizeof(Elf64_Sym
)), /* sh_offset */
921 1, /* sh_addralign */
929 (Elf64_Off
)(sizeof(header64
)+sizeof(sectionHeaders64
)+2*sizeof(Elf64_Sym
)+40), /* sh_offset */
930 (Elf64_Xword
)sizeof(entry
), /* sh_size */
933 1, /* sh_addralign */
939 SHF_ALLOC
, /* sh_flags */
941 (Elf64_Off
)(sizeof(header64
)+sizeof(sectionHeaders64
)+2*sizeof(Elf64_Sym
)+40+sizeof(entry
)), /* sh_offset */
945 16, /* sh_addralign */
951 * 64-bit symbol table
952 * careful: different order of items compared with Elf32_sym!
954 static Elf64_Sym symbols64
[2]={
958 { /* data entry point */
960 ELF64_ST_INFO(STB_GLOBAL
, STT_OBJECT
),
962 4, /* st_shndx=index of related section table entry */
970 /* entry[] have a leading NUL */
973 /* in the common code, count entryLength from after the NUL */
978 #elif defined(U_WINDOWS)
980 IMAGE_FILE_HEADER fileHeader
;
981 IMAGE_SECTION_HEADER sections
[2];
982 char linkerOptions
[100];
984 IMAGE_SYMBOL symbols
[1];
986 DWORD sizeofLongNames
;
991 * entry sometimes have a leading '_'
992 * overwritten if entryOffset==0 depending on the target platform
993 * see check for cpu below
999 # error "Unknown platform for CAN_GENERATE_OBJECTS."
1002 /* deal with options, files and the entry point name */
1003 getArchitecture(&cpu
, &bits
, &makeBigEndian
, optMatchArch
);
1004 printf("genccode: --match-arch cpu=%hu bits=%hu big-endian=%hu\n", cpu
, bits
, makeBigEndian
);
1006 if(cpu
==IMAGE_FILE_MACHINE_I386
) {
1011 in
=T_FileStream_open(filename
, "rb");
1013 fprintf(stderr
, "genccode: unable to open input file %s\n", filename
);
1014 exit(U_FILE_ACCESS_ERROR
);
1016 size
=T_FileStream_size(in
);
1018 getOutFilename(filename
, destdir
, buffer
, entry
+entryOffset
, newSuffix
, optFilename
);
1019 if (outFilePath
!= NULL
) {
1020 uprv_strcpy(outFilePath
, buffer
);
1023 if(optEntryPoint
!= NULL
) {
1024 uprv_strcpy(entry
+entryOffset
, optEntryPoint
);
1025 uprv_strcat(entry
+entryOffset
, "_dat");
1027 /* turn dashes in the entry name into underscores */
1028 entryLength
=(int32_t)uprv_strlen(entry
+entryLengthOffset
);
1029 for(i
=0; i
<entryLength
; ++i
) {
1030 if(entry
[entryLengthOffset
+i
]=='-') {
1031 entry
[entryLengthOffset
+i
]='_';
1035 /* open the output file */
1036 out
=T_FileStream_open(buffer
, "wb");
1038 fprintf(stderr
, "genccode: unable to open output file %s\n", buffer
);
1039 exit(U_FILE_ACCESS_ERROR
);
1044 header32
.e_ident
[EI_DATA
]= makeBigEndian
? ELFDATA2MSB
: ELFDATA2LSB
;
1045 header32
.e_machine
=cpu
;
1047 /* 16-align .rodata in the .o file, just in case */
1048 paddingSize
=sectionHeaders32
[4].sh_offset
& 0xf;
1049 if(paddingSize
!=0) {
1050 paddingSize
=0x10-paddingSize
;
1051 sectionHeaders32
[4].sh_offset
+=paddingSize
;
1054 sectionHeaders32
[4].sh_size
=(Elf32_Word
)size
;
1056 symbols32
[1].st_size
=(Elf32_Word
)size
;
1058 /* write .o headers */
1059 T_FileStream_write(out
, &header32
, (int32_t)sizeof(header32
));
1060 T_FileStream_write(out
, sectionHeaders32
, (int32_t)sizeof(sectionHeaders32
));
1061 T_FileStream_write(out
, symbols32
, (int32_t)sizeof(symbols32
));
1062 } else /* bits==64 */ {
1064 header64
.e_ident
[EI_DATA
]= makeBigEndian
? ELFDATA2MSB
: ELFDATA2LSB
;
1065 header64
.e_machine
=cpu
;
1067 /* 16-align .rodata in the .o file, just in case */
1068 paddingSize
=sectionHeaders64
[4].sh_offset
& 0xf;
1069 if(paddingSize
!=0) {
1070 paddingSize
=0x10-paddingSize
;
1071 sectionHeaders64
[4].sh_offset
+=paddingSize
;
1074 sectionHeaders64
[4].sh_size
=(Elf64_Xword
)size
;
1076 symbols64
[1].st_size
=(Elf64_Xword
)size
;
1078 /* write .o headers */
1079 T_FileStream_write(out
, &header64
, (int32_t)sizeof(header64
));
1080 T_FileStream_write(out
, sectionHeaders64
, (int32_t)sizeof(sectionHeaders64
));
1081 T_FileStream_write(out
, symbols64
, (int32_t)sizeof(symbols64
));
1085 T_FileStream_write(out
, sectionStrings
, (int32_t)sizeof(sectionStrings
));
1086 T_FileStream_write(out
, entry
, (int32_t)sizeof(entry
));
1087 if(paddingSize
!=0) {
1088 T_FileStream_write(out
, padding
, paddingSize
);
1090 #elif defined(U_WINDOWS)
1091 /* populate the .obj headers */
1092 uprv_memset(&objHeader
, 0, sizeof(objHeader
));
1093 uprv_memset(&symbols
, 0, sizeof(symbols
));
1094 uprv_memset(&symbolNames
, 0, sizeof(symbolNames
));
1096 /* write the linker export directive */
1097 uprv_strcpy(objHeader
.linkerOptions
, "-export:");
1099 uprv_strcpy(objHeader
.linkerOptions
+length
, entry
);
1100 length
+=entryLength
;
1101 uprv_strcpy(objHeader
.linkerOptions
+length
, ",data ");
1104 /* set the file header */
1105 objHeader
.fileHeader
.Machine
=cpu
;
1106 objHeader
.fileHeader
.NumberOfSections
=2;
1107 objHeader
.fileHeader
.TimeDateStamp
=(DWORD
)time(NULL
);
1108 objHeader
.fileHeader
.PointerToSymbolTable
=IMAGE_SIZEOF_FILE_HEADER
+2*IMAGE_SIZEOF_SECTION_HEADER
+length
+size
; /* start of symbol table */
1109 objHeader
.fileHeader
.NumberOfSymbols
=1;
1111 /* set the section for the linker options */
1112 uprv_strncpy((char *)objHeader
.sections
[0].Name
, ".drectve", 8);
1113 objHeader
.sections
[0].SizeOfRawData
=length
;
1114 objHeader
.sections
[0].PointerToRawData
=IMAGE_SIZEOF_FILE_HEADER
+2*IMAGE_SIZEOF_SECTION_HEADER
;
1115 objHeader
.sections
[0].Characteristics
=IMAGE_SCN_LNK_INFO
|IMAGE_SCN_LNK_REMOVE
|IMAGE_SCN_ALIGN_1BYTES
;
1117 /* set the data section */
1118 uprv_strncpy((char *)objHeader
.sections
[1].Name
, ".rdata", 6);
1119 objHeader
.sections
[1].SizeOfRawData
=size
;
1120 objHeader
.sections
[1].PointerToRawData
=IMAGE_SIZEOF_FILE_HEADER
+2*IMAGE_SIZEOF_SECTION_HEADER
+length
;
1121 objHeader
.sections
[1].Characteristics
=IMAGE_SCN_CNT_INITIALIZED_DATA
|IMAGE_SCN_ALIGN_16BYTES
|IMAGE_SCN_MEM_READ
;
1123 /* set the symbol table */
1124 if(entryLength
<=8) {
1125 uprv_strncpy((char *)symbols
[0].N
.ShortName
, entry
, entryLength
);
1126 symbolNames
.sizeofLongNames
=4;
1128 symbols
[0].N
.Name
.Short
=0;
1129 symbols
[0].N
.Name
.Long
=4;
1130 symbolNames
.sizeofLongNames
=4+entryLength
+1;
1131 uprv_strcpy(symbolNames
.longNames
, entry
);
1133 symbols
[0].SectionNumber
=2;
1134 symbols
[0].StorageClass
=IMAGE_SYM_CLASS_EXTERNAL
;
1136 /* write the file header and the linker options section */
1137 T_FileStream_write(out
, &objHeader
, objHeader
.sections
[1].PointerToRawData
);
1139 # error "Unknown platform for CAN_GENERATE_OBJECTS."
1142 /* copy the data file into section 2 */
1144 length
=T_FileStream_read(in
, buffer
, sizeof(buffer
));
1148 T_FileStream_write(out
, buffer
, (int32_t)length
);
1152 /* write the symbol table */
1153 T_FileStream_write(out
, symbols
, IMAGE_SIZEOF_SYMBOL
);
1154 T_FileStream_write(out
, &symbolNames
, symbolNames
.sizeofLongNames
);
1157 if(T_FileStream_error(in
)) {
1158 fprintf(stderr
, "genccode: file read error while generating from file %s\n", filename
);
1159 exit(U_FILE_ACCESS_ERROR
);
1162 if(T_FileStream_error(out
)) {
1163 fprintf(stderr
, "genccode: file write error while generating from file %s\n", filename
);
1164 exit(U_FILE_ACCESS_ERROR
);
1167 T_FileStream_close(out
);
1168 T_FileStream_close(in
);