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 */
55
* The following is needed by MinGW64
57
#ifndef __USER_LABEL_PREFIX__
58
#define __USER_LABEL_PREFIX__ _
60
#define GCC_LABEL_PREFIX_INTERNAL(a) #a
61
#define GCC_LABEL_PREFIX(a) GCC_LABEL_PREFIX_INTERNAL(a)
63
/* prototypes --------------------------------------------------------------- */
65
getOutFilename(const char *inFilename, const char *destdir, char *outFilename, char *entryName, const char *newSuffix, const char *optFilename);
68
write8(FileStream *out, uint8_t byte, uint32_t column);
71
write32(FileStream *out, uint32_t byte, uint32_t column);
73
#if U_PLATFORM == U_PF_OS400
75
write8str(FileStream *out, uint8_t byte, uint32_t column);
77
/* -------------------------------------------------------------------------- */
80
Creating Template Files for New Platforms
82
Let the cc compiler help you get started.
84
const unsigned int x[5] = {1, 2, 0xdeadbeef, 0xffffffff, 16};
85
with the -S option to produce assembly output.
87
For example, this will generate array.s:
90
This will produce a .s file that may look like this:
106
.ident "GCC: (GNU) 2.96 20000731 (Red Hat Linux 7.1 2.96-85)"
108
which gives a starting point that will compile, and can be transformed
109
to become the template, generally with some consulting of as docs and
110
some experimentation.
112
If you want ICU to automatically use this assembly, you should
113
specify "GENCCODE_ASSEMBLY=-a name" in the specific config/mh-* file,
114
where the name is the compiler or platform that you used in this
115
assemblyHeader data structure.
117
static const struct AssemblyType {
120
const char *beginLine;
122
int8_t hexType; /* HEX_0X or HEX_0h */
123
} assemblyHeader[] = {
126
"\t.section .note.GNU-stack,\"\",%%progbits\n"
127
"\t.section .rodata\n"
128
"\t.align 8\n" /* Either align 8 bytes or 2^8 (256) bytes. 8 bytes is needed. */
129
"\t.type %s,%%object\n"
135
/*"\t.section __TEXT,__text,regular,pure_instructions\n"
136
"\t.section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32\n"*/
140
"\t.align 4\n" /* 1<<4 = 16 */
146
".globl "GCC_LABEL_PREFIX(__USER_LABEL_PREFIX__) "%s\n"
147
"\t.section .rodata\n"
148
"\t.align 8\n" /* Either align 8 bytes or 2^8 (256) bytes. 8 bytes is needed. */
149
GCC_LABEL_PREFIX(__USER_LABEL_PREFIX__) "%s:\n\n",
154
"\t.section \".rodata\"\n"
163
"\t.type Drodata.rodata,@object\n"
164
"\t.size Drodata.rodata,0\n"
175
"\t.csect %s{RO}, 4\n",
181
"\t.type %s,@object\n"
183
"\t.secalias .abe$0.rodata, \".rodata\"\n"
184
"\t.section .abe$0.rodata = \"a\", \"progbits\"\n"
201
"; generated by genccode\n"
205
"ICUDATA_%s\tSEGMENT READONLY PARA PUBLIC FLAT 'DATA'\n"
207
"_%s\tLABEL DWORD\n",
208
"\tDWORD ","\nICUDATA_%s\tENDS\n\tEND\n",HEX_0H
212
static int32_t assemblyHeaderIndex = -1;
213
static int32_t hexType = HEX_0X;
215
U_CAPI UBool U_EXPORT2
216
checkAssemblyHeaderName(const char* optAssembly) {
218
assemblyHeaderIndex = -1;
219
for (idx = 0; idx < (int32_t)(sizeof(assemblyHeader)/sizeof(assemblyHeader[0])); idx++) {
220
if (uprv_strcmp(optAssembly, assemblyHeader[idx].name) == 0) {
221
assemblyHeaderIndex = idx;
222
hexType = assemblyHeader[idx].hexType; /* set the hex type */
231
U_CAPI void U_EXPORT2
232
printAssemblyHeadersToStdErr(void) {
234
fprintf(stderr, "%s", assemblyHeader[0].name);
235
for (idx = 1; idx < (int32_t)(sizeof(assemblyHeader)/sizeof(assemblyHeader[0])); idx++) {
236
fprintf(stderr, ", %s", assemblyHeader[idx].name);
242
U_CAPI void U_EXPORT2
243
writeAssemblyCode(const char *filename, const char *destdir, const char *optEntryPoint, const char *optFilename, char *outFilePath) {
244
uint32_t column = MAX_COLUMN;
246
uint32_t buffer[1024];
247
char *bufferStr = (char *)buffer;
248
FileStream *in, *out;
251
in=T_FileStream_open(filename, "rb");
253
fprintf(stderr, "genccode: unable to open input file %s\n", filename);
254
exit(U_FILE_ACCESS_ERROR);
257
getOutFilename(filename, destdir, bufferStr, entry, ".s", optFilename);
258
out=T_FileStream_open(bufferStr, "w");
260
fprintf(stderr, "genccode: unable to open output file %s\n", bufferStr);
261
exit(U_FILE_ACCESS_ERROR);
264
if (outFilePath != NULL) {
265
uprv_strcpy(outFilePath, bufferStr);
268
#ifdef WINDOWS_WITH_GNUC
269
/* Need to fix the file seperator character when using MinGW. */
270
swapFileSepChar(outFilePath, U_FILE_SEP_CHAR, '/');
273
if(optEntryPoint != NULL) {
274
uprv_strcpy(entry, optEntryPoint);
275
uprv_strcat(entry, "_dat");
278
/* turn dashes or dots in the entry name into underscores */
279
length=uprv_strlen(entry);
280
for(i=0; i<length; ++i) {
281
if(entry[i]=='-' || entry[i]=='.') {
286
sprintf(bufferStr, assemblyHeader[assemblyHeaderIndex].header,
287
entry, entry, entry, entry,
288
entry, entry, entry, entry);
289
T_FileStream_writeLine(out, bufferStr);
290
T_FileStream_writeLine(out, assemblyHeader[assemblyHeaderIndex].beginLine);
293
length=T_FileStream_read(in, buffer, sizeof(buffer));
297
if (length != sizeof(buffer)) {
298
/* pad with extra 0's when at the end of the file */
299
for(i=0; i < (length % sizeof(uint32_t)); ++i) {
300
buffer[length+i] = 0;
303
for(i=0; i<(length/sizeof(buffer[0])); i++) {
304
column = write32(out, buffer[i], column);
308
T_FileStream_writeLine(out, "\n");
310
sprintf(bufferStr, assemblyHeader[assemblyHeaderIndex].footer,
311
entry, entry, entry, entry,
312
entry, entry, entry, entry);
313
T_FileStream_writeLine(out, bufferStr);
315
if(T_FileStream_error(in)) {
316
fprintf(stderr, "genccode: file read error while generating from file %s\n", filename);
317
exit(U_FILE_ACCESS_ERROR);
320
if(T_FileStream_error(out)) {
321
fprintf(stderr, "genccode: file write error while generating from file %s\n", filename);
322
exit(U_FILE_ACCESS_ERROR);
325
T_FileStream_close(out);
326
T_FileStream_close(in);
329
U_CAPI void U_EXPORT2
330
writeCCode(const char *filename, const char *destdir, const char *optName, const char *optFilename, char *outFilePath) {
331
uint32_t column = MAX_COLUMN;
332
char buffer[4096], entry[64];
333
FileStream *in, *out;
336
in=T_FileStream_open(filename, "rb");
338
fprintf(stderr, "genccode: unable to open input file %s\n", filename);
339
exit(U_FILE_ACCESS_ERROR);
342
if(optName != NULL) { /* prepend 'icudt28_' */
343
strcpy(entry, optName);
349
getOutFilename(filename, destdir, buffer, entry+uprv_strlen(entry), ".c", optFilename);
350
if (outFilePath != NULL) {
351
uprv_strcpy(outFilePath, buffer);
353
out=T_FileStream_open(buffer, "w");
355
fprintf(stderr, "genccode: unable to open output file %s\n", buffer);
356
exit(U_FILE_ACCESS_ERROR);
359
/* turn dashes or dots in the entry name into underscores */
360
length=uprv_strlen(entry);
361
for(i=0; i<length; ++i) {
362
if(entry[i]=='-' || entry[i]=='.') {
367
#if U_PLATFORM == U_PF_OS400
369
TODO: Fix this once the compiler implements this feature. Keep in sync with udatamem.c
371
This is here because this platform can't currently put
372
const data into the read-only pages of an object or
373
shared library (service program). Only strings are allowed in read-only
374
pages, so we use char * strings to store the data.
376
In order to prevent the beginning of the data from ever matching the
377
magic numbers we must still use the initial double.
381
"#ifndef IN_GENERATED_CCODE\n"
382
"#define IN_GENERATED_CCODE\n"
383
"#define U_DISABLE_RENAMING 1\n"
384
"#include \"unicode/umachine.h\"\n"
389
" const char *bytes; \n"
392
T_FileStream_writeLine(out, buffer);
395
length=T_FileStream_read(in, buffer, sizeof(buffer));
399
for(i=0; i<length; ++i) {
400
column = write8str(out, (uint8_t)buffer[i], column);
404
T_FileStream_writeLine(out, "\"\n};\nU_CDECL_END\n");
406
/* Function renaming shouldn't be done in data */
408
"#ifndef IN_GENERATED_CCODE\n"
409
"#define IN_GENERATED_CCODE\n"
410
"#define U_DISABLE_RENAMING 1\n"
411
"#include \"unicode/umachine.h\"\n"
416
" uint8_t bytes[%ld]; \n"
418
(long)T_FileStream_size(in), entry);
419
T_FileStream_writeLine(out, buffer);
422
length=T_FileStream_read(in, buffer, sizeof(buffer));
426
for(i=0; i<length; ++i) {
427
column = write8(out, (uint8_t)buffer[i], column);
431
T_FileStream_writeLine(out, "\n}\n};\nU_CDECL_END\n");
434
if(T_FileStream_error(in)) {
435
fprintf(stderr, "genccode: file read error while generating from file %s\n", filename);
436
exit(U_FILE_ACCESS_ERROR);
439
if(T_FileStream_error(out)) {
440
fprintf(stderr, "genccode: file write error while generating from file %s\n", filename);
441
exit(U_FILE_ACCESS_ERROR);
444
T_FileStream_close(out);
445
T_FileStream_close(in);
449
write32(FileStream *out, uint32_t bitField, uint32_t column) {
451
char bitFieldStr[64]; /* This is more bits than needed for a 32-bit number */
452
char *s = bitFieldStr;
453
uint8_t *ptrIdx = (uint8_t *)&bitField;
454
static const char hexToStr[16] = {
461
/* write the value, possibly with comma and newline */
462
if(column==MAX_COLUMN) {
465
} else if(column<32) {
470
uprv_strcpy(s, assemblyHeader[assemblyHeaderIndex].beginLine);
476
/* It's a small number. Don't waste the space for 0x */
477
*(s++)=hexToStr[bitField];
480
int seenNonZero = 0; /* This is used to remove leading zeros */
482
if(hexType==HEX_0X) {
485
} else if(hexType==HEX_0H) {
489
/* This creates a 32-bit field */
491
for (i = 0; i < sizeof(uint32_t); i++)
493
for (i = sizeof(uint32_t)-1; i >= 0 ; i--)
496
uint8_t value = ptrIdx[i];
497
if (value || seenNonZero) {
498
*(s++)=hexToStr[value>>4];
499
*(s++)=hexToStr[value&0xF];
503
if(hexType==HEX_0H) {
509
T_FileStream_writeLine(out, bitFieldStr);
514
write8(FileStream *out, uint8_t byte, uint32_t column) {
518
/* convert the byte value to a string */
520
s[i++]=(char)('0'+byte/100);
523
if(i>0 || byte>=10) {
524
s[i++]=(char)('0'+byte/10);
527
s[i++]=(char)('0'+byte);
530
/* write the value, possibly with comma and newline */
531
if(column==MAX_COLUMN) {
534
} else if(column<16) {
535
T_FileStream_writeLine(out, ",");
538
T_FileStream_writeLine(out, ",\n");
541
T_FileStream_writeLine(out, s);
545
#if U_PLATFORM == U_PF_OS400
547
write8str(FileStream *out, uint8_t byte, uint32_t column) {
551
sprintf(s, "\\x%X", byte);
553
sprintf(s, "\\%X", byte);
555
/* write the value, possibly with comma and newline */
556
if(column==MAX_COLUMN) {
559
T_FileStream_writeLine(out, "\"");
560
} else if(column<24) {
563
T_FileStream_writeLine(out, "\"\n\"");
566
T_FileStream_writeLine(out, s);
572
getOutFilename(const char *inFilename, const char *destdir, char *outFilename, char *entryName, const char *newSuffix, const char *optFilename) {
573
const char *basename=findBasename(inFilename), *suffix=uprv_strrchr(basename, '.');
576
if(destdir!=NULL && *destdir!=0) {
578
*outFilename++=*destdir++;
579
} while(*destdir!=0);
580
if(*(outFilename-1)!=U_FILE_SEP_CHAR) {
581
*outFilename++=U_FILE_SEP_CHAR;
585
while(inFilename<basename) {
586
*outFilename++=*inFilename++;
591
/* the filename does not have a suffix */
592
uprv_strcpy(entryName, inFilename);
593
if(optFilename != NULL) {
594
uprv_strcpy(outFilename, optFilename);
596
uprv_strcpy(outFilename, inFilename);
598
uprv_strcat(outFilename, newSuffix);
600
char *saveOutFilename = outFilename;
602
while(inFilename<suffix) {
603
if(*inFilename=='-') {
604
/* iSeries cannot have '-' in the .o objects. */
605
*outFilename++=*entryName++='_';
609
*outFilename++=*entryName++=*inFilename++;
613
/* replace '.' by '_' */
614
*outFilename++=*entryName++='_';
618
while(*inFilename!=0) {
619
*outFilename++=*entryName++=*inFilename++;
624
if(optFilename != NULL) {
625
uprv_strcpy(saveOutFilename, optFilename);
626
uprv_strcat(saveOutFilename, newSuffix);
629
uprv_strcpy(outFilename, newSuffix);
634
#ifdef CAN_GENERATE_OBJECTS
636
getArchitecture(uint16_t *pCPU, uint16_t *pBits, UBool *pIsBigEndian, const char *optMatchArch) {
641
/* Elf32_Ehdr and ELF64_Ehdr are identical for the necessary fields. */
642
#elif U_PLATFORM_HAS_WIN32_API
643
IMAGE_FILE_HEADER header;
647
const char *filename;
653
#elif U_PLATFORM_HAS_WIN32_API
654
const IMAGE_FILE_HEADER *pHeader;
656
# error "Unknown platform for CAN_GENERATE_OBJECTS."
659
if(optMatchArch != NULL) {
660
filename=optMatchArch;
664
/* set EM_386 because elf.h does not provide better defaults */
667
*pIsBigEndian=(UBool)(U_IS_BIG_ENDIAN ? ELFDATA2MSB : ELFDATA2LSB);
668
#elif U_PLATFORM_HAS_WIN32_API
669
/* _M_IA64 should be defined in windows.h */
670
# if defined(_M_IA64)
671
*pCPU=IMAGE_FILE_MACHINE_IA64;
672
# elif defined(_M_AMD64)
673
*pCPU=IMAGE_FILE_MACHINE_AMD64;
675
*pCPU=IMAGE_FILE_MACHINE_I386;
677
*pBits= *pCPU==IMAGE_FILE_MACHINE_I386 ? 32 : 64;
680
# error "Unknown platform for CAN_GENERATE_OBJECTS."
685
in=T_FileStream_open(filename, "rb");
687
fprintf(stderr, "genccode: unable to open match-arch file %s\n", filename);
688
exit(U_FILE_ACCESS_ERROR);
690
length=T_FileStream_read(in, buffer.bytes, sizeof(buffer.bytes));
693
if(length<sizeof(Elf32_Ehdr)) {
694
fprintf(stderr, "genccode: match-arch file %s is too short\n", filename);
695
exit(U_UNSUPPORTED_ERROR);
698
buffer.header32.e_ident[0]!=ELFMAG0 ||
699
buffer.header32.e_ident[1]!=ELFMAG1 ||
700
buffer.header32.e_ident[2]!=ELFMAG2 ||
701
buffer.header32.e_ident[3]!=ELFMAG3 ||
702
buffer.header32.e_ident[EI_CLASS]<ELFCLASS32 || buffer.header32.e_ident[EI_CLASS]>ELFCLASS64
704
fprintf(stderr, "genccode: match-arch file %s is not an ELF object file, or not supported\n", filename);
705
exit(U_UNSUPPORTED_ERROR);
708
*pBits= buffer.header32.e_ident[EI_CLASS]==ELFCLASS32 ? 32 : 64; /* only 32 or 64: see check above */
710
if(*pBits!=32 && *pBits!=64) {
711
fprintf(stderr, "genccode: currently only supports 32-bit and 64-bit ELF format\n");
712
exit(U_UNSUPPORTED_ERROR);
716
fprintf(stderr, "genccode: built with elf.h missing 64-bit definitions\n");
717
exit(U_UNSUPPORTED_ERROR);
721
*pIsBigEndian=(UBool)(buffer.header32.e_ident[EI_DATA]==ELFDATA2MSB);
722
if(*pIsBigEndian!=U_IS_BIG_ENDIAN) {
723
fprintf(stderr, "genccode: currently only same-endianness ELF formats are supported\n");
724
exit(U_UNSUPPORTED_ERROR);
726
/* TODO: Support byte swapping */
728
*pCPU=buffer.header32.e_machine;
729
#elif U_PLATFORM_HAS_WIN32_API
730
if(length<sizeof(IMAGE_FILE_HEADER)) {
731
fprintf(stderr, "genccode: match-arch file %s is too short\n", filename);
732
exit(U_UNSUPPORTED_ERROR);
734
/* TODO: Use buffer.header. Keep aliasing legal. */
735
pHeader=(const IMAGE_FILE_HEADER *)buffer.bytes;
736
*pCPU=pHeader->Machine;
738
* The number of bits is implicit with the Machine value.
739
* *pBits is ignored in the calling code, so this need not be precise.
741
*pBits= *pCPU==IMAGE_FILE_MACHINE_I386 ? 32 : 64;
742
/* Windows always runs on little-endian CPUs. */
745
# error "Unknown platform for CAN_GENERATE_OBJECTS."
748
T_FileStream_close(in);
751
U_CAPI void U_EXPORT2
752
writeObjectCode(const char *filename, const char *destdir, const char *optEntryPoint, const char *optMatchArch, const char *optFilename, char *outFilePath) {
753
/* common variables */
754
char buffer[4096], entry[40]={ 0 };
755
FileStream *in, *out;
756
const char *newSuffix;
757
int32_t i, entryLength, length, size, entryOffset=0, entryLengthOffset=0;
762
/* platform-specific variables and initialization code */
764
/* 32-bit Elf file header */
765
static Elf32_Ehdr header32={
768
ELFMAG0, ELFMAG1, ELFMAG2, ELFMAG3,
770
U_IS_BIG_ENDIAN ? ELFDATA2MSB : ELFDATA2LSB,
771
EV_CURRENT /* EI_VERSION */
775
EV_CURRENT, /* e_version */
778
(Elf32_Off)sizeof(Elf32_Ehdr), /* e_shoff */
780
(Elf32_Half)sizeof(Elf32_Ehdr), /* eh_size */
783
(Elf32_Half)sizeof(Elf32_Shdr), /* e_shentsize */
788
/* 32-bit Elf section header table */
789
static Elf32_Shdr sectionHeaders32[5]={
798
(Elf32_Off)(sizeof(header32)+sizeof(sectionHeaders32)), /* sh_offset */
799
(Elf32_Word)(2*sizeof(Elf32_Sym)), /* sh_size */
800
3, /* sh_link=sect hdr index of .strtab */
801
1, /* sh_info=One greater than the symbol table index of the last
802
* local symbol (with STB_LOCAL). */
803
4, /* sh_addralign */
804
(Elf32_Word)(sizeof(Elf32_Sym)) /* sh_entsize */
811
(Elf32_Off)(sizeof(header32)+sizeof(sectionHeaders32)+2*sizeof(Elf32_Sym)), /* sh_offset */
815
1, /* sh_addralign */
823
(Elf32_Off)(sizeof(header32)+sizeof(sectionHeaders32)+2*sizeof(Elf32_Sym)+40), /* sh_offset */
824
(Elf32_Word)sizeof(entry), /* sh_size */
827
1, /* sh_addralign */
833
SHF_ALLOC, /* sh_flags */
835
(Elf32_Off)(sizeof(header32)+sizeof(sectionHeaders32)+2*sizeof(Elf32_Sym)+40+sizeof(entry)), /* sh_offset */
839
16, /* sh_addralign */
845
static Elf32_Sym symbols32[2]={
849
{ /* data entry point */
853
ELF64_ST_INFO(STB_GLOBAL, STT_OBJECT),
855
4 /* st_shndx=index of related section table entry */
859
/* section header string table, with decimal string offsets */
860
static const char sectionStrings[40]=
863
/* 9 */ ".shstrtab\0"
866
/* 35 */ "\0\0\0\0"; /* contains terminating NUL */
867
/* 40: padded to multiple of 8 bytes */
870
* Use entry[] for the string table which will contain only the
872
* entry[0] must be 0 (NUL)
873
* The entry point name can be up to 38 characters long (sizeof(entry)-2).
876
/* 16-align .rodata in the .o file, just in case */
877
static const char padding[16]={ 0 };
881
/* 64-bit Elf file header */
882
static Elf64_Ehdr header64={
885
ELFMAG0, ELFMAG1, ELFMAG2, ELFMAG3,
887
U_IS_BIG_ENDIAN ? ELFDATA2MSB : ELFDATA2LSB,
888
EV_CURRENT /* EI_VERSION */
892
EV_CURRENT, /* e_version */
895
(Elf64_Off)sizeof(Elf64_Ehdr), /* e_shoff */
897
(Elf64_Half)sizeof(Elf64_Ehdr), /* eh_size */
900
(Elf64_Half)sizeof(Elf64_Shdr), /* e_shentsize */
905
/* 64-bit Elf section header table */
906
static Elf64_Shdr sectionHeaders64[5]={
915
(Elf64_Off)(sizeof(header64)+sizeof(sectionHeaders64)), /* sh_offset */
916
(Elf64_Xword)(2*sizeof(Elf64_Sym)), /* sh_size */
917
3, /* sh_link=sect hdr index of .strtab */
918
1, /* sh_info=One greater than the symbol table index of the last
919
* local symbol (with STB_LOCAL). */
920
4, /* sh_addralign */
921
(Elf64_Xword)(sizeof(Elf64_Sym)) /* sh_entsize */
928
(Elf64_Off)(sizeof(header64)+sizeof(sectionHeaders64)+2*sizeof(Elf64_Sym)), /* sh_offset */
932
1, /* sh_addralign */
940
(Elf64_Off)(sizeof(header64)+sizeof(sectionHeaders64)+2*sizeof(Elf64_Sym)+40), /* sh_offset */
941
(Elf64_Xword)sizeof(entry), /* sh_size */
944
1, /* sh_addralign */
950
SHF_ALLOC, /* sh_flags */
952
(Elf64_Off)(sizeof(header64)+sizeof(sectionHeaders64)+2*sizeof(Elf64_Sym)+40+sizeof(entry)), /* sh_offset */
956
16, /* sh_addralign */
962
* 64-bit symbol table
963
* careful: different order of items compared with Elf32_sym!
965
static Elf64_Sym symbols64[2]={
969
{ /* data entry point */
971
ELF64_ST_INFO(STB_GLOBAL, STT_OBJECT),
973
4, /* st_shndx=index of related section table entry */
981
/* entry[] have a leading NUL */
984
/* in the common code, count entryLength from after the NUL */
989
#elif U_PLATFORM_HAS_WIN32_API
991
IMAGE_FILE_HEADER fileHeader;
992
IMAGE_SECTION_HEADER sections[2];
993
char linkerOptions[100];
995
IMAGE_SYMBOL symbols[1];
997
DWORD sizeofLongNames;
1002
* entry sometimes have a leading '_'
1003
* overwritten if entryOffset==0 depending on the target platform
1004
* see check for cpu below
1010
# error "Unknown platform for CAN_GENERATE_OBJECTS."
1013
/* deal with options, files and the entry point name */
1014
getArchitecture(&cpu, &bits, &makeBigEndian, optMatchArch);
1015
printf("genccode: --match-arch cpu=%hu bits=%hu big-endian=%d\n", cpu, bits, makeBigEndian);
1016
#if U_PLATFORM_HAS_WIN32_API
1017
if(cpu==IMAGE_FILE_MACHINE_I386) {
1022
in=T_FileStream_open(filename, "rb");
1024
fprintf(stderr, "genccode: unable to open input file %s\n", filename);
1025
exit(U_FILE_ACCESS_ERROR);
1027
size=T_FileStream_size(in);
1029
getOutFilename(filename, destdir, buffer, entry+entryOffset, newSuffix, optFilename);
1030
if (outFilePath != NULL) {
1031
uprv_strcpy(outFilePath, buffer);
1034
if(optEntryPoint != NULL) {
1035
uprv_strcpy(entry+entryOffset, optEntryPoint);
1036
uprv_strcat(entry+entryOffset, "_dat");
1038
/* turn dashes in the entry name into underscores */
1039
entryLength=(int32_t)uprv_strlen(entry+entryLengthOffset);
1040
for(i=0; i<entryLength; ++i) {
1041
if(entry[entryLengthOffset+i]=='-') {
1042
entry[entryLengthOffset+i]='_';
1046
/* open the output file */
1047
out=T_FileStream_open(buffer, "wb");
1049
fprintf(stderr, "genccode: unable to open output file %s\n", buffer);
1050
exit(U_FILE_ACCESS_ERROR);
1055
header32.e_ident[EI_DATA]= makeBigEndian ? ELFDATA2MSB : ELFDATA2LSB;
1056
header32.e_machine=cpu;
1058
/* 16-align .rodata in the .o file, just in case */
1059
paddingSize=sectionHeaders32[4].sh_offset & 0xf;
1060
if(paddingSize!=0) {
1061
paddingSize=0x10-paddingSize;
1062
sectionHeaders32[4].sh_offset+=paddingSize;
1065
sectionHeaders32[4].sh_size=(Elf32_Word)size;
1067
symbols32[1].st_size=(Elf32_Word)size;
1069
/* write .o headers */
1070
T_FileStream_write(out, &header32, (int32_t)sizeof(header32));
1071
T_FileStream_write(out, sectionHeaders32, (int32_t)sizeof(sectionHeaders32));
1072
T_FileStream_write(out, symbols32, (int32_t)sizeof(symbols32));
1073
} else /* bits==64 */ {
1075
header64.e_ident[EI_DATA]= makeBigEndian ? ELFDATA2MSB : ELFDATA2LSB;
1076
header64.e_machine=cpu;
1078
/* 16-align .rodata in the .o file, just in case */
1079
paddingSize=sectionHeaders64[4].sh_offset & 0xf;
1080
if(paddingSize!=0) {
1081
paddingSize=0x10-paddingSize;
1082
sectionHeaders64[4].sh_offset+=paddingSize;
1085
sectionHeaders64[4].sh_size=(Elf64_Xword)size;
1087
symbols64[1].st_size=(Elf64_Xword)size;
1089
/* write .o headers */
1090
T_FileStream_write(out, &header64, (int32_t)sizeof(header64));
1091
T_FileStream_write(out, sectionHeaders64, (int32_t)sizeof(sectionHeaders64));
1092
T_FileStream_write(out, symbols64, (int32_t)sizeof(symbols64));
1096
T_FileStream_write(out, sectionStrings, (int32_t)sizeof(sectionStrings));
1097
T_FileStream_write(out, entry, (int32_t)sizeof(entry));
1098
if(paddingSize!=0) {
1099
T_FileStream_write(out, padding, paddingSize);
1101
#elif U_PLATFORM_HAS_WIN32_API
1102
/* populate the .obj headers */
1103
uprv_memset(&objHeader, 0, sizeof(objHeader));
1104
uprv_memset(&symbols, 0, sizeof(symbols));
1105
uprv_memset(&symbolNames, 0, sizeof(symbolNames));
1107
/* write the linker export directive */
1108
uprv_strcpy(objHeader.linkerOptions, "-export:");
1110
uprv_strcpy(objHeader.linkerOptions+length, entry);
1111
length+=entryLength;
1112
uprv_strcpy(objHeader.linkerOptions+length, ",data ");
1115
/* set the file header */
1116
objHeader.fileHeader.Machine=cpu;
1117
objHeader.fileHeader.NumberOfSections=2;
1118
objHeader.fileHeader.TimeDateStamp=(DWORD)time(NULL);
1119
objHeader.fileHeader.PointerToSymbolTable=IMAGE_SIZEOF_FILE_HEADER+2*IMAGE_SIZEOF_SECTION_HEADER+length+size; /* start of symbol table */
1120
objHeader.fileHeader.NumberOfSymbols=1;
1122
/* set the section for the linker options */
1123
uprv_strncpy((char *)objHeader.sections[0].Name, ".drectve", 8);
1124
objHeader.sections[0].SizeOfRawData=length;
1125
objHeader.sections[0].PointerToRawData=IMAGE_SIZEOF_FILE_HEADER+2*IMAGE_SIZEOF_SECTION_HEADER;
1126
objHeader.sections[0].Characteristics=IMAGE_SCN_LNK_INFO|IMAGE_SCN_LNK_REMOVE|IMAGE_SCN_ALIGN_1BYTES;
1128
/* set the data section */
1129
uprv_strncpy((char *)objHeader.sections[1].Name, ".rdata", 6);
1130
objHeader.sections[1].SizeOfRawData=size;
1131
objHeader.sections[1].PointerToRawData=IMAGE_SIZEOF_FILE_HEADER+2*IMAGE_SIZEOF_SECTION_HEADER+length;
1132
objHeader.sections[1].Characteristics=IMAGE_SCN_CNT_INITIALIZED_DATA|IMAGE_SCN_ALIGN_16BYTES|IMAGE_SCN_MEM_READ;
1134
/* set the symbol table */
1135
if(entryLength<=8) {
1136
uprv_strncpy((char *)symbols[0].N.ShortName, entry, entryLength);
1137
symbolNames.sizeofLongNames=4;
1139
symbols[0].N.Name.Short=0;
1140
symbols[0].N.Name.Long=4;
1141
symbolNames.sizeofLongNames=4+entryLength+1;
1142
uprv_strcpy(symbolNames.longNames, entry);
1144
symbols[0].SectionNumber=2;
1145
symbols[0].StorageClass=IMAGE_SYM_CLASS_EXTERNAL;
1147
/* write the file header and the linker options section */
1148
T_FileStream_write(out, &objHeader, objHeader.sections[1].PointerToRawData);
1150
# error "Unknown platform for CAN_GENERATE_OBJECTS."
1153
/* copy the data file into section 2 */
1155
length=T_FileStream_read(in, buffer, sizeof(buffer));
1159
T_FileStream_write(out, buffer, (int32_t)length);
1162
#if U_PLATFORM_HAS_WIN32_API
1163
/* write the symbol table */
1164
T_FileStream_write(out, symbols, IMAGE_SIZEOF_SYMBOL);
1165
T_FileStream_write(out, &symbolNames, symbolNames.sizeofLongNames);
1168
if(T_FileStream_error(in)) {
1169
fprintf(stderr, "genccode: file read error while generating from file %s\n", filename);
1170
exit(U_FILE_ACCESS_ERROR);
1173
if(T_FileStream_error(out)) {
1174
fprintf(stderr, "genccode: file write error while generating from file %s\n", filename);
1175
exit(U_FILE_ACCESS_ERROR);
1178
T_FileStream_close(out);
1179
T_FileStream_close(in);