1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/intl/icu/source/tools/toolutil/pkg_genc.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,1191 @@ 1.4 +/****************************************************************************** 1.5 + * Copyright (C) 2009-2013, International Business Machines 1.6 + * Corporation and others. All Rights Reserved. 1.7 + ******************************************************************************* 1.8 + */ 1.9 +#include "unicode/utypes.h" 1.10 + 1.11 +#if U_PLATFORM_HAS_WIN32_API 1.12 +# define VC_EXTRALEAN 1.13 +# define WIN32_LEAN_AND_MEAN 1.14 +# define NOUSER 1.15 +# define NOSERVICE 1.16 +# define NOIME 1.17 +# define NOMCX 1.18 +#include <windows.h> 1.19 +#include <time.h> 1.20 +# ifdef __GNUC__ 1.21 +# define WINDOWS_WITH_GNUC 1.22 +# endif 1.23 +#endif 1.24 + 1.25 +#if U_PLATFORM_IS_LINUX_BASED && U_HAVE_ELF_H 1.26 +# define U_ELF 1.27 +#endif 1.28 + 1.29 +#ifdef U_ELF 1.30 +# include <elf.h> 1.31 +# if defined(ELFCLASS64) 1.32 +# define U_ELF64 1.33 +# endif 1.34 + /* Old elf.h headers may not have EM_X86_64, or have EM_X8664 instead. */ 1.35 +# ifndef EM_X86_64 1.36 +# define EM_X86_64 62 1.37 +# endif 1.38 +# define ICU_ENTRY_OFFSET 0 1.39 +#endif 1.40 + 1.41 +#include <stdio.h> 1.42 +#include <stdlib.h> 1.43 +#include "unicode/putil.h" 1.44 +#include "cmemory.h" 1.45 +#include "cstring.h" 1.46 +#include "filestrm.h" 1.47 +#include "toolutil.h" 1.48 +#include "unicode/uclean.h" 1.49 +#include "uoptions.h" 1.50 +#include "pkg_genc.h" 1.51 + 1.52 +#define MAX_COLUMN ((uint32_t)(0xFFFFFFFFU)) 1.53 + 1.54 +#define HEX_0X 0 /* 0x1234 */ 1.55 +#define HEX_0H 1 /* 01234h */ 1.56 + 1.57 +/* prototypes --------------------------------------------------------------- */ 1.58 +static void 1.59 +getOutFilename(const char *inFilename, const char *destdir, char *outFilename, char *entryName, const char *newSuffix, const char *optFilename); 1.60 + 1.61 +static uint32_t 1.62 +write8(FileStream *out, uint8_t byte, uint32_t column); 1.63 + 1.64 +static uint32_t 1.65 +write32(FileStream *out, uint32_t byte, uint32_t column); 1.66 + 1.67 +#if U_PLATFORM == U_PF_OS400 1.68 +static uint32_t 1.69 +write8str(FileStream *out, uint8_t byte, uint32_t column); 1.70 +#endif 1.71 +/* -------------------------------------------------------------------------- */ 1.72 + 1.73 +/* 1.74 +Creating Template Files for New Platforms 1.75 + 1.76 +Let the cc compiler help you get started. 1.77 +Compile this program 1.78 + const unsigned int x[5] = {1, 2, 0xdeadbeef, 0xffffffff, 16}; 1.79 +with the -S option to produce assembly output. 1.80 + 1.81 +For example, this will generate array.s: 1.82 +gcc -S array.c 1.83 + 1.84 +This will produce a .s file that may look like this: 1.85 + 1.86 + .file "array.c" 1.87 + .version "01.01" 1.88 +gcc2_compiled.: 1.89 + .globl x 1.90 + .section .rodata 1.91 + .align 4 1.92 + .type x,@object 1.93 + .size x,20 1.94 +x: 1.95 + .long 1 1.96 + .long 2 1.97 + .long -559038737 1.98 + .long -1 1.99 + .long 16 1.100 + .ident "GCC: (GNU) 2.96 20000731 (Red Hat Linux 7.1 2.96-85)" 1.101 + 1.102 +which gives a starting point that will compile, and can be transformed 1.103 +to become the template, generally with some consulting of as docs and 1.104 +some experimentation. 1.105 + 1.106 +If you want ICU to automatically use this assembly, you should 1.107 +specify "GENCCODE_ASSEMBLY=-a name" in the specific config/mh-* file, 1.108 +where the name is the compiler or platform that you used in this 1.109 +assemblyHeader data structure. 1.110 +*/ 1.111 +static const struct AssemblyType { 1.112 + const char *name; 1.113 + const char *header; 1.114 + const char *beginLine; 1.115 + const char *footer; 1.116 + int8_t hexType; /* HEX_0X or HEX_0h */ 1.117 +} assemblyHeader[] = { 1.118 + // For gcc assemblers, the meaning of .align changes depending on the 1.119 + // hardware, so we use .balign 16 which always means 16 bytes. 1.120 + // https://sourceware.org/binutils/docs/as/Pseudo-Ops.html 1.121 + {"gcc", 1.122 + ".globl %s\n" 1.123 + "\t.section .note.GNU-stack,\"\",%%progbits\n" 1.124 + "\t.section .rodata\n" 1.125 + "\t.balign 16\n" 1.126 + "\t.type %s,%%object\n" 1.127 + "%s:\n\n", 1.128 + 1.129 + ".long ","",HEX_0X 1.130 + }, 1.131 + {"gcc-darwin", 1.132 + /*"\t.section __TEXT,__text,regular,pure_instructions\n" 1.133 + "\t.section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32\n"*/ 1.134 + ".globl _%s\n" 1.135 + "\t.data\n" 1.136 + "\t.const\n" 1.137 + "\t.balign 16\n" 1.138 + "_%s:\n\n", 1.139 + 1.140 + ".long ","",HEX_0X 1.141 + }, 1.142 + {"gcc-cygwin", 1.143 + ".globl _%s\n" 1.144 + "\t.section .rodata\n" 1.145 + "\t.balign 16\n" 1.146 + "_%s:\n\n", 1.147 + 1.148 + ".long ","",HEX_0X 1.149 + }, 1.150 + {"gcc-mingw64", 1.151 + ".globl %s\n" 1.152 + "\t.section .rodata\n" 1.153 + "\t.balign 16\n" 1.154 + "%s:\n\n", 1.155 + 1.156 + ".long ","",HEX_0X 1.157 + }, 1.158 +// 16 bytes alignment. 1.159 +// http://docs.oracle.com/cd/E19641-01/802-1947/802-1947.pdf 1.160 + {"sun", 1.161 + "\t.section \".rodata\"\n" 1.162 + "\t.align 16\n" 1.163 + ".globl %s\n" 1.164 + "%s:\n", 1.165 + 1.166 + ".word ","",HEX_0X 1.167 + }, 1.168 +// 16 bytes alignment for sun-x86. 1.169 +// http://docs.oracle.com/cd/E19963-01/html/821-1608/eoiyg.html 1.170 + {"sun-x86", 1.171 + "Drodata.rodata:\n" 1.172 + "\t.type Drodata.rodata,@object\n" 1.173 + "\t.size Drodata.rodata,0\n" 1.174 + "\t.globl %s\n" 1.175 + "\t.align 16\n" 1.176 + "%s:\n", 1.177 + 1.178 + ".4byte ","",HEX_0X 1.179 + }, 1.180 +// 1<<4 bit alignment for aix. 1.181 +// http://pic.dhe.ibm.com/infocenter/aix/v6r1/index.jsp?topic=%2Fcom.ibm.aix.aixassem%2Fdoc%2Falangref%2Fidalangref_csect_pseudoop.htm 1.182 + {"xlc", 1.183 + ".globl %s{RO}\n" 1.184 + "\t.toc\n" 1.185 + "%s:\n" 1.186 + "\t.csect %s{RO}, 4\n", 1.187 + 1.188 + ".long ","",HEX_0X 1.189 + }, 1.190 + {"aCC-ia64", 1.191 + "\t.file \"%s.s\"\n" 1.192 + "\t.type %s,@object\n" 1.193 + "\t.global %s\n" 1.194 + "\t.secalias .abe$0.rodata, \".rodata\"\n" 1.195 + "\t.section .abe$0.rodata = \"a\", \"progbits\"\n" 1.196 + "\t.align 16\n" 1.197 + "%s::\t", 1.198 + 1.199 + "data4 ","",HEX_0X 1.200 + }, 1.201 + {"aCC-parisc", 1.202 + "\t.SPACE $TEXT$\n" 1.203 + "\t.SUBSPA $LIT$\n" 1.204 + "%s\n" 1.205 + "\t.EXPORT %s\n" 1.206 + "\t.ALIGN 16\n", 1.207 + 1.208 + ".WORD ","",HEX_0X 1.209 + }, 1.210 +// align 16 bytes 1.211 +// http://msdn.microsoft.com/en-us/library/dwa9fwef.aspx 1.212 + { "masm", 1.213 + "\tTITLE %s\n" 1.214 + "; generated by genccode\n" 1.215 + ".386\n" 1.216 + ".model flat\n" 1.217 + "\tPUBLIC _%s\n" 1.218 + "ICUDATA_%s\tSEGMENT READONLY PARA PUBLIC FLAT 'DATA'\n" 1.219 + "\tALIGN 16\n" 1.220 + "_%s\tLABEL DWORD\n", 1.221 + "\tDWORD ","\nICUDATA_%s\tENDS\n\tEND\n",HEX_0H 1.222 + } 1.223 +}; 1.224 + 1.225 +static int32_t assemblyHeaderIndex = -1; 1.226 +static int32_t hexType = HEX_0X; 1.227 + 1.228 +U_CAPI UBool U_EXPORT2 1.229 +checkAssemblyHeaderName(const char* optAssembly) { 1.230 + int32_t idx; 1.231 + assemblyHeaderIndex = -1; 1.232 + for (idx = 0; idx < (int32_t)(sizeof(assemblyHeader)/sizeof(assemblyHeader[0])); idx++) { 1.233 + if (uprv_strcmp(optAssembly, assemblyHeader[idx].name) == 0) { 1.234 + assemblyHeaderIndex = idx; 1.235 + hexType = assemblyHeader[idx].hexType; /* set the hex type */ 1.236 + return TRUE; 1.237 + } 1.238 + } 1.239 + 1.240 + return FALSE; 1.241 +} 1.242 + 1.243 + 1.244 +U_CAPI void U_EXPORT2 1.245 +printAssemblyHeadersToStdErr(void) { 1.246 + int32_t idx; 1.247 + fprintf(stderr, "%s", assemblyHeader[0].name); 1.248 + for (idx = 1; idx < (int32_t)(sizeof(assemblyHeader)/sizeof(assemblyHeader[0])); idx++) { 1.249 + fprintf(stderr, ", %s", assemblyHeader[idx].name); 1.250 + } 1.251 + fprintf(stderr, 1.252 + ")\n"); 1.253 +} 1.254 + 1.255 +U_CAPI void U_EXPORT2 1.256 +writeAssemblyCode(const char *filename, const char *destdir, const char *optEntryPoint, const char *optFilename, char *outFilePath) { 1.257 + uint32_t column = MAX_COLUMN; 1.258 + char entry[64]; 1.259 + uint32_t buffer[1024]; 1.260 + char *bufferStr = (char *)buffer; 1.261 + FileStream *in, *out; 1.262 + size_t i, length; 1.263 + 1.264 + in=T_FileStream_open(filename, "rb"); 1.265 + if(in==NULL) { 1.266 + fprintf(stderr, "genccode: unable to open input file %s\n", filename); 1.267 + exit(U_FILE_ACCESS_ERROR); 1.268 + } 1.269 + 1.270 + getOutFilename(filename, destdir, bufferStr, entry, ".s", optFilename); 1.271 + out=T_FileStream_open(bufferStr, "w"); 1.272 + if(out==NULL) { 1.273 + fprintf(stderr, "genccode: unable to open output file %s\n", bufferStr); 1.274 + exit(U_FILE_ACCESS_ERROR); 1.275 + } 1.276 + 1.277 + if (outFilePath != NULL) { 1.278 + uprv_strcpy(outFilePath, bufferStr); 1.279 + } 1.280 + 1.281 +#ifdef WINDOWS_WITH_GNUC 1.282 + /* Need to fix the file seperator character when using MinGW. */ 1.283 + swapFileSepChar(outFilePath, U_FILE_SEP_CHAR, '/'); 1.284 +#endif 1.285 + 1.286 + if(optEntryPoint != NULL) { 1.287 + uprv_strcpy(entry, optEntryPoint); 1.288 + uprv_strcat(entry, "_dat"); 1.289 + } 1.290 + 1.291 + /* turn dashes or dots in the entry name into underscores */ 1.292 + length=uprv_strlen(entry); 1.293 + for(i=0; i<length; ++i) { 1.294 + if(entry[i]=='-' || entry[i]=='.') { 1.295 + entry[i]='_'; 1.296 + } 1.297 + } 1.298 + 1.299 + sprintf(bufferStr, assemblyHeader[assemblyHeaderIndex].header, 1.300 + entry, entry, entry, entry, 1.301 + entry, entry, entry, entry); 1.302 + T_FileStream_writeLine(out, bufferStr); 1.303 + T_FileStream_writeLine(out, assemblyHeader[assemblyHeaderIndex].beginLine); 1.304 + 1.305 + for(;;) { 1.306 + length=T_FileStream_read(in, buffer, sizeof(buffer)); 1.307 + if(length==0) { 1.308 + break; 1.309 + } 1.310 + if (length != sizeof(buffer)) { 1.311 + /* pad with extra 0's when at the end of the file */ 1.312 + for(i=0; i < (length % sizeof(uint32_t)); ++i) { 1.313 + buffer[length+i] = 0; 1.314 + } 1.315 + } 1.316 + for(i=0; i<(length/sizeof(buffer[0])); i++) { 1.317 + column = write32(out, buffer[i], column); 1.318 + } 1.319 + } 1.320 + 1.321 + T_FileStream_writeLine(out, "\n"); 1.322 + 1.323 + sprintf(bufferStr, assemblyHeader[assemblyHeaderIndex].footer, 1.324 + entry, entry, entry, entry, 1.325 + entry, entry, entry, entry); 1.326 + T_FileStream_writeLine(out, bufferStr); 1.327 + 1.328 + if(T_FileStream_error(in)) { 1.329 + fprintf(stderr, "genccode: file read error while generating from file %s\n", filename); 1.330 + exit(U_FILE_ACCESS_ERROR); 1.331 + } 1.332 + 1.333 + if(T_FileStream_error(out)) { 1.334 + fprintf(stderr, "genccode: file write error while generating from file %s\n", filename); 1.335 + exit(U_FILE_ACCESS_ERROR); 1.336 + } 1.337 + 1.338 + T_FileStream_close(out); 1.339 + T_FileStream_close(in); 1.340 +} 1.341 + 1.342 +U_CAPI void U_EXPORT2 1.343 +writeCCode(const char *filename, const char *destdir, const char *optName, const char *optFilename, char *outFilePath) { 1.344 + uint32_t column = MAX_COLUMN; 1.345 + char buffer[4096], entry[64]; 1.346 + FileStream *in, *out; 1.347 + size_t i, length; 1.348 + 1.349 + in=T_FileStream_open(filename, "rb"); 1.350 + if(in==NULL) { 1.351 + fprintf(stderr, "genccode: unable to open input file %s\n", filename); 1.352 + exit(U_FILE_ACCESS_ERROR); 1.353 + } 1.354 + 1.355 + if(optName != NULL) { /* prepend 'icudt28_' */ 1.356 + strcpy(entry, optName); 1.357 + strcat(entry, "_"); 1.358 + } else { 1.359 + entry[0] = 0; 1.360 + } 1.361 + 1.362 + getOutFilename(filename, destdir, buffer, entry+uprv_strlen(entry), ".c", optFilename); 1.363 + if (outFilePath != NULL) { 1.364 + uprv_strcpy(outFilePath, buffer); 1.365 + } 1.366 + out=T_FileStream_open(buffer, "w"); 1.367 + if(out==NULL) { 1.368 + fprintf(stderr, "genccode: unable to open output file %s\n", buffer); 1.369 + exit(U_FILE_ACCESS_ERROR); 1.370 + } 1.371 + 1.372 + /* turn dashes or dots in the entry name into underscores */ 1.373 + length=uprv_strlen(entry); 1.374 + for(i=0; i<length; ++i) { 1.375 + if(entry[i]=='-' || entry[i]=='.') { 1.376 + entry[i]='_'; 1.377 + } 1.378 + } 1.379 + 1.380 +#if U_PLATFORM == U_PF_OS400 1.381 + /* 1.382 + TODO: Fix this once the compiler implements this feature. Keep in sync with udatamem.c 1.383 + 1.384 + This is here because this platform can't currently put 1.385 + const data into the read-only pages of an object or 1.386 + shared library (service program). Only strings are allowed in read-only 1.387 + pages, so we use char * strings to store the data. 1.388 + 1.389 + In order to prevent the beginning of the data from ever matching the 1.390 + magic numbers we must still use the initial double. 1.391 + [grhoten 4/24/2003] 1.392 + */ 1.393 + sprintf(buffer, 1.394 + "#ifndef IN_GENERATED_CCODE\n" 1.395 + "#define IN_GENERATED_CCODE\n" 1.396 + "#define U_DISABLE_RENAMING 1\n" 1.397 + "#include \"unicode/umachine.h\"\n" 1.398 + "#endif\n" 1.399 + "U_CDECL_BEGIN\n" 1.400 + "const struct {\n" 1.401 + " double bogus;\n" 1.402 + " const char *bytes; \n" 1.403 + "} %s={ 0.0, \n", 1.404 + entry); 1.405 + T_FileStream_writeLine(out, buffer); 1.406 + 1.407 + for(;;) { 1.408 + length=T_FileStream_read(in, buffer, sizeof(buffer)); 1.409 + if(length==0) { 1.410 + break; 1.411 + } 1.412 + for(i=0; i<length; ++i) { 1.413 + column = write8str(out, (uint8_t)buffer[i], column); 1.414 + } 1.415 + } 1.416 + 1.417 + T_FileStream_writeLine(out, "\"\n};\nU_CDECL_END\n"); 1.418 +#else 1.419 + /* Function renaming shouldn't be done in data */ 1.420 + sprintf(buffer, 1.421 + "#ifndef IN_GENERATED_CCODE\n" 1.422 + "#define IN_GENERATED_CCODE\n" 1.423 + "#define U_DISABLE_RENAMING 1\n" 1.424 + "#include \"unicode/umachine.h\"\n" 1.425 + "#endif\n" 1.426 + "U_CDECL_BEGIN\n" 1.427 + "const struct {\n" 1.428 + " double bogus;\n" 1.429 + " uint8_t bytes[%ld]; \n" 1.430 + "} %s={ 0.0, {\n", 1.431 + (long)T_FileStream_size(in), entry); 1.432 + T_FileStream_writeLine(out, buffer); 1.433 + 1.434 + for(;;) { 1.435 + length=T_FileStream_read(in, buffer, sizeof(buffer)); 1.436 + if(length==0) { 1.437 + break; 1.438 + } 1.439 + for(i=0; i<length; ++i) { 1.440 + column = write8(out, (uint8_t)buffer[i], column); 1.441 + } 1.442 + } 1.443 + 1.444 + T_FileStream_writeLine(out, "\n}\n};\nU_CDECL_END\n"); 1.445 +#endif 1.446 + 1.447 + if(T_FileStream_error(in)) { 1.448 + fprintf(stderr, "genccode: file read error while generating from file %s\n", filename); 1.449 + exit(U_FILE_ACCESS_ERROR); 1.450 + } 1.451 + 1.452 + if(T_FileStream_error(out)) { 1.453 + fprintf(stderr, "genccode: file write error while generating from file %s\n", filename); 1.454 + exit(U_FILE_ACCESS_ERROR); 1.455 + } 1.456 + 1.457 + T_FileStream_close(out); 1.458 + T_FileStream_close(in); 1.459 +} 1.460 + 1.461 +static uint32_t 1.462 +write32(FileStream *out, uint32_t bitField, uint32_t column) { 1.463 + int32_t i; 1.464 + char bitFieldStr[64]; /* This is more bits than needed for a 32-bit number */ 1.465 + char *s = bitFieldStr; 1.466 + uint8_t *ptrIdx = (uint8_t *)&bitField; 1.467 + static const char hexToStr[16] = { 1.468 + '0','1','2','3', 1.469 + '4','5','6','7', 1.470 + '8','9','A','B', 1.471 + 'C','D','E','F' 1.472 + }; 1.473 + 1.474 + /* write the value, possibly with comma and newline */ 1.475 + if(column==MAX_COLUMN) { 1.476 + /* first byte */ 1.477 + column=1; 1.478 + } else if(column<32) { 1.479 + *(s++)=','; 1.480 + ++column; 1.481 + } else { 1.482 + *(s++)='\n'; 1.483 + uprv_strcpy(s, assemblyHeader[assemblyHeaderIndex].beginLine); 1.484 + s+=uprv_strlen(s); 1.485 + column=1; 1.486 + } 1.487 + 1.488 + if (bitField < 10) { 1.489 + /* It's a small number. Don't waste the space for 0x */ 1.490 + *(s++)=hexToStr[bitField]; 1.491 + } 1.492 + else { 1.493 + int seenNonZero = 0; /* This is used to remove leading zeros */ 1.494 + 1.495 + if(hexType==HEX_0X) { 1.496 + *(s++)='0'; 1.497 + *(s++)='x'; 1.498 + } else if(hexType==HEX_0H) { 1.499 + *(s++)='0'; 1.500 + } 1.501 + 1.502 + /* This creates a 32-bit field */ 1.503 +#if U_IS_BIG_ENDIAN 1.504 + for (i = 0; i < sizeof(uint32_t); i++) 1.505 +#else 1.506 + for (i = sizeof(uint32_t)-1; i >= 0 ; i--) 1.507 +#endif 1.508 + { 1.509 + uint8_t value = ptrIdx[i]; 1.510 + if (value || seenNonZero) { 1.511 + *(s++)=hexToStr[value>>4]; 1.512 + *(s++)=hexToStr[value&0xF]; 1.513 + seenNonZero = 1; 1.514 + } 1.515 + } 1.516 + if(hexType==HEX_0H) { 1.517 + *(s++)='h'; 1.518 + } 1.519 + } 1.520 + 1.521 + *(s++)=0; 1.522 + T_FileStream_writeLine(out, bitFieldStr); 1.523 + return column; 1.524 +} 1.525 + 1.526 +static uint32_t 1.527 +write8(FileStream *out, uint8_t byte, uint32_t column) { 1.528 + char s[4]; 1.529 + int i=0; 1.530 + 1.531 + /* convert the byte value to a string */ 1.532 + if(byte>=100) { 1.533 + s[i++]=(char)('0'+byte/100); 1.534 + byte%=100; 1.535 + } 1.536 + if(i>0 || byte>=10) { 1.537 + s[i++]=(char)('0'+byte/10); 1.538 + byte%=10; 1.539 + } 1.540 + s[i++]=(char)('0'+byte); 1.541 + s[i]=0; 1.542 + 1.543 + /* write the value, possibly with comma and newline */ 1.544 + if(column==MAX_COLUMN) { 1.545 + /* first byte */ 1.546 + column=1; 1.547 + } else if(column<16) { 1.548 + T_FileStream_writeLine(out, ","); 1.549 + ++column; 1.550 + } else { 1.551 + T_FileStream_writeLine(out, ",\n"); 1.552 + column=1; 1.553 + } 1.554 + T_FileStream_writeLine(out, s); 1.555 + return column; 1.556 +} 1.557 + 1.558 +#if U_PLATFORM == U_PF_OS400 1.559 +static uint32_t 1.560 +write8str(FileStream *out, uint8_t byte, uint32_t column) { 1.561 + char s[8]; 1.562 + 1.563 + if (byte > 7) 1.564 + sprintf(s, "\\x%X", byte); 1.565 + else 1.566 + sprintf(s, "\\%X", byte); 1.567 + 1.568 + /* write the value, possibly with comma and newline */ 1.569 + if(column==MAX_COLUMN) { 1.570 + /* first byte */ 1.571 + column=1; 1.572 + T_FileStream_writeLine(out, "\""); 1.573 + } else if(column<24) { 1.574 + ++column; 1.575 + } else { 1.576 + T_FileStream_writeLine(out, "\"\n\""); 1.577 + column=1; 1.578 + } 1.579 + T_FileStream_writeLine(out, s); 1.580 + return column; 1.581 +} 1.582 +#endif 1.583 + 1.584 +static void 1.585 +getOutFilename(const char *inFilename, const char *destdir, char *outFilename, char *entryName, const char *newSuffix, const char *optFilename) { 1.586 + const char *basename=findBasename(inFilename), *suffix=uprv_strrchr(basename, '.'); 1.587 + 1.588 + /* copy path */ 1.589 + if(destdir!=NULL && *destdir!=0) { 1.590 + do { 1.591 + *outFilename++=*destdir++; 1.592 + } while(*destdir!=0); 1.593 + if(*(outFilename-1)!=U_FILE_SEP_CHAR) { 1.594 + *outFilename++=U_FILE_SEP_CHAR; 1.595 + } 1.596 + inFilename=basename; 1.597 + } else { 1.598 + while(inFilename<basename) { 1.599 + *outFilename++=*inFilename++; 1.600 + } 1.601 + } 1.602 + 1.603 + if(suffix==NULL) { 1.604 + /* the filename does not have a suffix */ 1.605 + uprv_strcpy(entryName, inFilename); 1.606 + if(optFilename != NULL) { 1.607 + uprv_strcpy(outFilename, optFilename); 1.608 + } else { 1.609 + uprv_strcpy(outFilename, inFilename); 1.610 + } 1.611 + uprv_strcat(outFilename, newSuffix); 1.612 + } else { 1.613 + char *saveOutFilename = outFilename; 1.614 + /* copy basename */ 1.615 + while(inFilename<suffix) { 1.616 + if(*inFilename=='-') { 1.617 + /* iSeries cannot have '-' in the .o objects. */ 1.618 + *outFilename++=*entryName++='_'; 1.619 + inFilename++; 1.620 + } 1.621 + else { 1.622 + *outFilename++=*entryName++=*inFilename++; 1.623 + } 1.624 + } 1.625 + 1.626 + /* replace '.' by '_' */ 1.627 + *outFilename++=*entryName++='_'; 1.628 + ++inFilename; 1.629 + 1.630 + /* copy suffix */ 1.631 + while(*inFilename!=0) { 1.632 + *outFilename++=*entryName++=*inFilename++; 1.633 + } 1.634 + 1.635 + *entryName=0; 1.636 + 1.637 + if(optFilename != NULL) { 1.638 + uprv_strcpy(saveOutFilename, optFilename); 1.639 + uprv_strcat(saveOutFilename, newSuffix); 1.640 + } else { 1.641 + /* add ".c" */ 1.642 + uprv_strcpy(outFilename, newSuffix); 1.643 + } 1.644 + } 1.645 +} 1.646 + 1.647 +#ifdef CAN_GENERATE_OBJECTS 1.648 +static void 1.649 +getArchitecture(uint16_t *pCPU, uint16_t *pBits, UBool *pIsBigEndian, const char *optMatchArch) { 1.650 + union { 1.651 + char bytes[2048]; 1.652 +#ifdef U_ELF 1.653 + Elf32_Ehdr header32; 1.654 + /* Elf32_Ehdr and ELF64_Ehdr are identical for the necessary fields. */ 1.655 +#elif U_PLATFORM_HAS_WIN32_API 1.656 + IMAGE_FILE_HEADER header; 1.657 +#endif 1.658 + } buffer; 1.659 + 1.660 + const char *filename; 1.661 + FileStream *in; 1.662 + int32_t length; 1.663 + 1.664 +#ifdef U_ELF 1.665 + 1.666 +#elif U_PLATFORM_HAS_WIN32_API 1.667 + const IMAGE_FILE_HEADER *pHeader; 1.668 +#else 1.669 +# error "Unknown platform for CAN_GENERATE_OBJECTS." 1.670 +#endif 1.671 + 1.672 + if(optMatchArch != NULL) { 1.673 + filename=optMatchArch; 1.674 + } else { 1.675 + /* set defaults */ 1.676 +#ifdef U_ELF 1.677 + /* set EM_386 because elf.h does not provide better defaults */ 1.678 + *pCPU=EM_386; 1.679 + *pBits=32; 1.680 + *pIsBigEndian=(UBool)(U_IS_BIG_ENDIAN ? ELFDATA2MSB : ELFDATA2LSB); 1.681 +#elif U_PLATFORM_HAS_WIN32_API 1.682 +/* _M_IA64 should be defined in windows.h */ 1.683 +# if defined(_M_IA64) 1.684 + *pCPU=IMAGE_FILE_MACHINE_IA64; 1.685 +# elif defined(_M_AMD64) 1.686 + *pCPU=IMAGE_FILE_MACHINE_AMD64; 1.687 +# else 1.688 + *pCPU=IMAGE_FILE_MACHINE_I386; 1.689 +# endif 1.690 + *pBits= *pCPU==IMAGE_FILE_MACHINE_I386 ? 32 : 64; 1.691 + *pIsBigEndian=FALSE; 1.692 +#else 1.693 +# error "Unknown platform for CAN_GENERATE_OBJECTS." 1.694 +#endif 1.695 + return; 1.696 + } 1.697 + 1.698 + in=T_FileStream_open(filename, "rb"); 1.699 + if(in==NULL) { 1.700 + fprintf(stderr, "genccode: unable to open match-arch file %s\n", filename); 1.701 + exit(U_FILE_ACCESS_ERROR); 1.702 + } 1.703 + length=T_FileStream_read(in, buffer.bytes, sizeof(buffer.bytes)); 1.704 + 1.705 +#ifdef U_ELF 1.706 + if(length<sizeof(Elf32_Ehdr)) { 1.707 + fprintf(stderr, "genccode: match-arch file %s is too short\n", filename); 1.708 + exit(U_UNSUPPORTED_ERROR); 1.709 + } 1.710 + if( 1.711 + buffer.header32.e_ident[0]!=ELFMAG0 || 1.712 + buffer.header32.e_ident[1]!=ELFMAG1 || 1.713 + buffer.header32.e_ident[2]!=ELFMAG2 || 1.714 + buffer.header32.e_ident[3]!=ELFMAG3 || 1.715 + buffer.header32.e_ident[EI_CLASS]<ELFCLASS32 || buffer.header32.e_ident[EI_CLASS]>ELFCLASS64 1.716 + ) { 1.717 + fprintf(stderr, "genccode: match-arch file %s is not an ELF object file, or not supported\n", filename); 1.718 + exit(U_UNSUPPORTED_ERROR); 1.719 + } 1.720 + 1.721 + *pBits= buffer.header32.e_ident[EI_CLASS]==ELFCLASS32 ? 32 : 64; /* only 32 or 64: see check above */ 1.722 +#ifdef U_ELF64 1.723 + if(*pBits!=32 && *pBits!=64) { 1.724 + fprintf(stderr, "genccode: currently only supports 32-bit and 64-bit ELF format\n"); 1.725 + exit(U_UNSUPPORTED_ERROR); 1.726 + } 1.727 +#else 1.728 + if(*pBits!=32) { 1.729 + fprintf(stderr, "genccode: built with elf.h missing 64-bit definitions\n"); 1.730 + exit(U_UNSUPPORTED_ERROR); 1.731 + } 1.732 +#endif 1.733 + 1.734 + *pIsBigEndian=(UBool)(buffer.header32.e_ident[EI_DATA]==ELFDATA2MSB); 1.735 + if(*pIsBigEndian!=U_IS_BIG_ENDIAN) { 1.736 + fprintf(stderr, "genccode: currently only same-endianness ELF formats are supported\n"); 1.737 + exit(U_UNSUPPORTED_ERROR); 1.738 + } 1.739 + /* TODO: Support byte swapping */ 1.740 + 1.741 + *pCPU=buffer.header32.e_machine; 1.742 +#elif U_PLATFORM_HAS_WIN32_API 1.743 + if(length<sizeof(IMAGE_FILE_HEADER)) { 1.744 + fprintf(stderr, "genccode: match-arch file %s is too short\n", filename); 1.745 + exit(U_UNSUPPORTED_ERROR); 1.746 + } 1.747 + /* TODO: Use buffer.header. Keep aliasing legal. */ 1.748 + pHeader=(const IMAGE_FILE_HEADER *)buffer.bytes; 1.749 + *pCPU=pHeader->Machine; 1.750 + /* 1.751 + * The number of bits is implicit with the Machine value. 1.752 + * *pBits is ignored in the calling code, so this need not be precise. 1.753 + */ 1.754 + *pBits= *pCPU==IMAGE_FILE_MACHINE_I386 ? 32 : 64; 1.755 + /* Windows always runs on little-endian CPUs. */ 1.756 + *pIsBigEndian=FALSE; 1.757 +#else 1.758 +# error "Unknown platform for CAN_GENERATE_OBJECTS." 1.759 +#endif 1.760 + 1.761 + T_FileStream_close(in); 1.762 +} 1.763 + 1.764 +U_CAPI void U_EXPORT2 1.765 +writeObjectCode(const char *filename, const char *destdir, const char *optEntryPoint, const char *optMatchArch, const char *optFilename, char *outFilePath) { 1.766 + /* common variables */ 1.767 + char buffer[4096], entry[40]={ 0 }; 1.768 + FileStream *in, *out; 1.769 + const char *newSuffix; 1.770 + int32_t i, entryLength, length, size, entryOffset=0, entryLengthOffset=0; 1.771 + 1.772 + uint16_t cpu, bits; 1.773 + UBool makeBigEndian; 1.774 + 1.775 + /* platform-specific variables and initialization code */ 1.776 +#ifdef U_ELF 1.777 + /* 32-bit Elf file header */ 1.778 + static Elf32_Ehdr header32={ 1.779 + { 1.780 + /* e_ident[] */ 1.781 + ELFMAG0, ELFMAG1, ELFMAG2, ELFMAG3, 1.782 + ELFCLASS32, 1.783 + U_IS_BIG_ENDIAN ? ELFDATA2MSB : ELFDATA2LSB, 1.784 + EV_CURRENT /* EI_VERSION */ 1.785 + }, 1.786 + ET_REL, 1.787 + EM_386, 1.788 + EV_CURRENT, /* e_version */ 1.789 + 0, /* e_entry */ 1.790 + 0, /* e_phoff */ 1.791 + (Elf32_Off)sizeof(Elf32_Ehdr), /* e_shoff */ 1.792 + 0, /* e_flags */ 1.793 + (Elf32_Half)sizeof(Elf32_Ehdr), /* eh_size */ 1.794 + 0, /* e_phentsize */ 1.795 + 0, /* e_phnum */ 1.796 + (Elf32_Half)sizeof(Elf32_Shdr), /* e_shentsize */ 1.797 + 5, /* e_shnum */ 1.798 + 2 /* e_shstrndx */ 1.799 + }; 1.800 + 1.801 + /* 32-bit Elf section header table */ 1.802 + static Elf32_Shdr sectionHeaders32[5]={ 1.803 + { /* SHN_UNDEF */ 1.804 + 0 1.805 + }, 1.806 + { /* .symtab */ 1.807 + 1, /* sh_name */ 1.808 + SHT_SYMTAB, 1.809 + 0, /* sh_flags */ 1.810 + 0, /* sh_addr */ 1.811 + (Elf32_Off)(sizeof(header32)+sizeof(sectionHeaders32)), /* sh_offset */ 1.812 + (Elf32_Word)(2*sizeof(Elf32_Sym)), /* sh_size */ 1.813 + 3, /* sh_link=sect hdr index of .strtab */ 1.814 + 1, /* sh_info=One greater than the symbol table index of the last 1.815 + * local symbol (with STB_LOCAL). */ 1.816 + 4, /* sh_addralign */ 1.817 + (Elf32_Word)(sizeof(Elf32_Sym)) /* sh_entsize */ 1.818 + }, 1.819 + { /* .shstrtab */ 1.820 + 9, /* sh_name */ 1.821 + SHT_STRTAB, 1.822 + 0, /* sh_flags */ 1.823 + 0, /* sh_addr */ 1.824 + (Elf32_Off)(sizeof(header32)+sizeof(sectionHeaders32)+2*sizeof(Elf32_Sym)), /* sh_offset */ 1.825 + 40, /* sh_size */ 1.826 + 0, /* sh_link */ 1.827 + 0, /* sh_info */ 1.828 + 1, /* sh_addralign */ 1.829 + 0 /* sh_entsize */ 1.830 + }, 1.831 + { /* .strtab */ 1.832 + 19, /* sh_name */ 1.833 + SHT_STRTAB, 1.834 + 0, /* sh_flags */ 1.835 + 0, /* sh_addr */ 1.836 + (Elf32_Off)(sizeof(header32)+sizeof(sectionHeaders32)+2*sizeof(Elf32_Sym)+40), /* sh_offset */ 1.837 + (Elf32_Word)sizeof(entry), /* sh_size */ 1.838 + 0, /* sh_link */ 1.839 + 0, /* sh_info */ 1.840 + 1, /* sh_addralign */ 1.841 + 0 /* sh_entsize */ 1.842 + }, 1.843 + { /* .rodata */ 1.844 + 27, /* sh_name */ 1.845 + SHT_PROGBITS, 1.846 + SHF_ALLOC, /* sh_flags */ 1.847 + 0, /* sh_addr */ 1.848 + (Elf32_Off)(sizeof(header32)+sizeof(sectionHeaders32)+2*sizeof(Elf32_Sym)+40+sizeof(entry)), /* sh_offset */ 1.849 + 0, /* sh_size */ 1.850 + 0, /* sh_link */ 1.851 + 0, /* sh_info */ 1.852 + 16, /* sh_addralign */ 1.853 + 0 /* sh_entsize */ 1.854 + } 1.855 + }; 1.856 + 1.857 + /* symbol table */ 1.858 + static Elf32_Sym symbols32[2]={ 1.859 + { /* STN_UNDEF */ 1.860 + 0 1.861 + }, 1.862 + { /* data entry point */ 1.863 + 1, /* st_name */ 1.864 + 0, /* st_value */ 1.865 + 0, /* st_size */ 1.866 + ELF64_ST_INFO(STB_GLOBAL, STT_OBJECT), 1.867 + 0, /* st_other */ 1.868 + 4 /* st_shndx=index of related section table entry */ 1.869 + } 1.870 + }; 1.871 + 1.872 + /* section header string table, with decimal string offsets */ 1.873 + static const char sectionStrings[40]= 1.874 + /* 0 */ "\0" 1.875 + /* 1 */ ".symtab\0" 1.876 + /* 9 */ ".shstrtab\0" 1.877 + /* 19 */ ".strtab\0" 1.878 + /* 27 */ ".rodata\0" 1.879 + /* 35 */ "\0\0\0\0"; /* contains terminating NUL */ 1.880 + /* 40: padded to multiple of 8 bytes */ 1.881 + 1.882 + /* 1.883 + * Use entry[] for the string table which will contain only the 1.884 + * entry point name. 1.885 + * entry[0] must be 0 (NUL) 1.886 + * The entry point name can be up to 38 characters long (sizeof(entry)-2). 1.887 + */ 1.888 + 1.889 + /* 16-align .rodata in the .o file, just in case */ 1.890 + static const char padding[16]={ 0 }; 1.891 + int32_t paddingSize; 1.892 + 1.893 +#ifdef U_ELF64 1.894 + /* 64-bit Elf file header */ 1.895 + static Elf64_Ehdr header64={ 1.896 + { 1.897 + /* e_ident[] */ 1.898 + ELFMAG0, ELFMAG1, ELFMAG2, ELFMAG3, 1.899 + ELFCLASS64, 1.900 + U_IS_BIG_ENDIAN ? ELFDATA2MSB : ELFDATA2LSB, 1.901 + EV_CURRENT /* EI_VERSION */ 1.902 + }, 1.903 + ET_REL, 1.904 + EM_X86_64, 1.905 + EV_CURRENT, /* e_version */ 1.906 + 0, /* e_entry */ 1.907 + 0, /* e_phoff */ 1.908 + (Elf64_Off)sizeof(Elf64_Ehdr), /* e_shoff */ 1.909 + 0, /* e_flags */ 1.910 + (Elf64_Half)sizeof(Elf64_Ehdr), /* eh_size */ 1.911 + 0, /* e_phentsize */ 1.912 + 0, /* e_phnum */ 1.913 + (Elf64_Half)sizeof(Elf64_Shdr), /* e_shentsize */ 1.914 + 5, /* e_shnum */ 1.915 + 2 /* e_shstrndx */ 1.916 + }; 1.917 + 1.918 + /* 64-bit Elf section header table */ 1.919 + static Elf64_Shdr sectionHeaders64[5]={ 1.920 + { /* SHN_UNDEF */ 1.921 + 0 1.922 + }, 1.923 + { /* .symtab */ 1.924 + 1, /* sh_name */ 1.925 + SHT_SYMTAB, 1.926 + 0, /* sh_flags */ 1.927 + 0, /* sh_addr */ 1.928 + (Elf64_Off)(sizeof(header64)+sizeof(sectionHeaders64)), /* sh_offset */ 1.929 + (Elf64_Xword)(2*sizeof(Elf64_Sym)), /* sh_size */ 1.930 + 3, /* sh_link=sect hdr index of .strtab */ 1.931 + 1, /* sh_info=One greater than the symbol table index of the last 1.932 + * local symbol (with STB_LOCAL). */ 1.933 + 4, /* sh_addralign */ 1.934 + (Elf64_Xword)(sizeof(Elf64_Sym)) /* sh_entsize */ 1.935 + }, 1.936 + { /* .shstrtab */ 1.937 + 9, /* sh_name */ 1.938 + SHT_STRTAB, 1.939 + 0, /* sh_flags */ 1.940 + 0, /* sh_addr */ 1.941 + (Elf64_Off)(sizeof(header64)+sizeof(sectionHeaders64)+2*sizeof(Elf64_Sym)), /* sh_offset */ 1.942 + 40, /* sh_size */ 1.943 + 0, /* sh_link */ 1.944 + 0, /* sh_info */ 1.945 + 1, /* sh_addralign */ 1.946 + 0 /* sh_entsize */ 1.947 + }, 1.948 + { /* .strtab */ 1.949 + 19, /* sh_name */ 1.950 + SHT_STRTAB, 1.951 + 0, /* sh_flags */ 1.952 + 0, /* sh_addr */ 1.953 + (Elf64_Off)(sizeof(header64)+sizeof(sectionHeaders64)+2*sizeof(Elf64_Sym)+40), /* sh_offset */ 1.954 + (Elf64_Xword)sizeof(entry), /* sh_size */ 1.955 + 0, /* sh_link */ 1.956 + 0, /* sh_info */ 1.957 + 1, /* sh_addralign */ 1.958 + 0 /* sh_entsize */ 1.959 + }, 1.960 + { /* .rodata */ 1.961 + 27, /* sh_name */ 1.962 + SHT_PROGBITS, 1.963 + SHF_ALLOC, /* sh_flags */ 1.964 + 0, /* sh_addr */ 1.965 + (Elf64_Off)(sizeof(header64)+sizeof(sectionHeaders64)+2*sizeof(Elf64_Sym)+40+sizeof(entry)), /* sh_offset */ 1.966 + 0, /* sh_size */ 1.967 + 0, /* sh_link */ 1.968 + 0, /* sh_info */ 1.969 + 16, /* sh_addralign */ 1.970 + 0 /* sh_entsize */ 1.971 + } 1.972 + }; 1.973 + 1.974 + /* 1.975 + * 64-bit symbol table 1.976 + * careful: different order of items compared with Elf32_sym! 1.977 + */ 1.978 + static Elf64_Sym symbols64[2]={ 1.979 + { /* STN_UNDEF */ 1.980 + 0 1.981 + }, 1.982 + { /* data entry point */ 1.983 + 1, /* st_name */ 1.984 + ELF64_ST_INFO(STB_GLOBAL, STT_OBJECT), 1.985 + 0, /* st_other */ 1.986 + 4, /* st_shndx=index of related section table entry */ 1.987 + 0, /* st_value */ 1.988 + 0 /* st_size */ 1.989 + } 1.990 + }; 1.991 + 1.992 +#endif /* U_ELF64 */ 1.993 + 1.994 + /* entry[] have a leading NUL */ 1.995 + entryOffset=1; 1.996 + 1.997 + /* in the common code, count entryLength from after the NUL */ 1.998 + entryLengthOffset=1; 1.999 + 1.1000 + newSuffix=".o"; 1.1001 + 1.1002 +#elif U_PLATFORM_HAS_WIN32_API 1.1003 + struct { 1.1004 + IMAGE_FILE_HEADER fileHeader; 1.1005 + IMAGE_SECTION_HEADER sections[2]; 1.1006 + char linkerOptions[100]; 1.1007 + } objHeader; 1.1008 + IMAGE_SYMBOL symbols[1]; 1.1009 + struct { 1.1010 + DWORD sizeofLongNames; 1.1011 + char longNames[100]; 1.1012 + } symbolNames; 1.1013 + 1.1014 + /* 1.1015 + * entry sometimes have a leading '_' 1.1016 + * overwritten if entryOffset==0 depending on the target platform 1.1017 + * see check for cpu below 1.1018 + */ 1.1019 + entry[0]='_'; 1.1020 + 1.1021 + newSuffix=".obj"; 1.1022 +#else 1.1023 +# error "Unknown platform for CAN_GENERATE_OBJECTS." 1.1024 +#endif 1.1025 + 1.1026 + /* deal with options, files and the entry point name */ 1.1027 + getArchitecture(&cpu, &bits, &makeBigEndian, optMatchArch); 1.1028 + printf("genccode: --match-arch cpu=%hu bits=%hu big-endian=%d\n", cpu, bits, makeBigEndian); 1.1029 +#if U_PLATFORM_HAS_WIN32_API 1.1030 + if(cpu==IMAGE_FILE_MACHINE_I386) { 1.1031 + entryOffset=1; 1.1032 + } 1.1033 +#endif 1.1034 + 1.1035 + in=T_FileStream_open(filename, "rb"); 1.1036 + if(in==NULL) { 1.1037 + fprintf(stderr, "genccode: unable to open input file %s\n", filename); 1.1038 + exit(U_FILE_ACCESS_ERROR); 1.1039 + } 1.1040 + size=T_FileStream_size(in); 1.1041 + 1.1042 + getOutFilename(filename, destdir, buffer, entry+entryOffset, newSuffix, optFilename); 1.1043 + if (outFilePath != NULL) { 1.1044 + uprv_strcpy(outFilePath, buffer); 1.1045 + } 1.1046 + 1.1047 + if(optEntryPoint != NULL) { 1.1048 + uprv_strcpy(entry+entryOffset, optEntryPoint); 1.1049 + uprv_strcat(entry+entryOffset, "_dat"); 1.1050 + } 1.1051 + /* turn dashes in the entry name into underscores */ 1.1052 + entryLength=(int32_t)uprv_strlen(entry+entryLengthOffset); 1.1053 + for(i=0; i<entryLength; ++i) { 1.1054 + if(entry[entryLengthOffset+i]=='-') { 1.1055 + entry[entryLengthOffset+i]='_'; 1.1056 + } 1.1057 + } 1.1058 + 1.1059 + /* open the output file */ 1.1060 + out=T_FileStream_open(buffer, "wb"); 1.1061 + if(out==NULL) { 1.1062 + fprintf(stderr, "genccode: unable to open output file %s\n", buffer); 1.1063 + exit(U_FILE_ACCESS_ERROR); 1.1064 + } 1.1065 + 1.1066 +#ifdef U_ELF 1.1067 + if(bits==32) { 1.1068 + header32.e_ident[EI_DATA]= makeBigEndian ? ELFDATA2MSB : ELFDATA2LSB; 1.1069 + header32.e_machine=cpu; 1.1070 + 1.1071 + /* 16-align .rodata in the .o file, just in case */ 1.1072 + paddingSize=sectionHeaders32[4].sh_offset & 0xf; 1.1073 + if(paddingSize!=0) { 1.1074 + paddingSize=0x10-paddingSize; 1.1075 + sectionHeaders32[4].sh_offset+=paddingSize; 1.1076 + } 1.1077 + 1.1078 + sectionHeaders32[4].sh_size=(Elf32_Word)size; 1.1079 + 1.1080 + symbols32[1].st_size=(Elf32_Word)size; 1.1081 + 1.1082 + /* write .o headers */ 1.1083 + T_FileStream_write(out, &header32, (int32_t)sizeof(header32)); 1.1084 + T_FileStream_write(out, sectionHeaders32, (int32_t)sizeof(sectionHeaders32)); 1.1085 + T_FileStream_write(out, symbols32, (int32_t)sizeof(symbols32)); 1.1086 + } else /* bits==64 */ { 1.1087 +#ifdef U_ELF64 1.1088 + header64.e_ident[EI_DATA]= makeBigEndian ? ELFDATA2MSB : ELFDATA2LSB; 1.1089 + header64.e_machine=cpu; 1.1090 + 1.1091 + /* 16-align .rodata in the .o file, just in case */ 1.1092 + paddingSize=sectionHeaders64[4].sh_offset & 0xf; 1.1093 + if(paddingSize!=0) { 1.1094 + paddingSize=0x10-paddingSize; 1.1095 + sectionHeaders64[4].sh_offset+=paddingSize; 1.1096 + } 1.1097 + 1.1098 + sectionHeaders64[4].sh_size=(Elf64_Xword)size; 1.1099 + 1.1100 + symbols64[1].st_size=(Elf64_Xword)size; 1.1101 + 1.1102 + /* write .o headers */ 1.1103 + T_FileStream_write(out, &header64, (int32_t)sizeof(header64)); 1.1104 + T_FileStream_write(out, sectionHeaders64, (int32_t)sizeof(sectionHeaders64)); 1.1105 + T_FileStream_write(out, symbols64, (int32_t)sizeof(symbols64)); 1.1106 +#endif 1.1107 + } 1.1108 + 1.1109 + T_FileStream_write(out, sectionStrings, (int32_t)sizeof(sectionStrings)); 1.1110 + T_FileStream_write(out, entry, (int32_t)sizeof(entry)); 1.1111 + if(paddingSize!=0) { 1.1112 + T_FileStream_write(out, padding, paddingSize); 1.1113 + } 1.1114 +#elif U_PLATFORM_HAS_WIN32_API 1.1115 + /* populate the .obj headers */ 1.1116 + uprv_memset(&objHeader, 0, sizeof(objHeader)); 1.1117 + uprv_memset(&symbols, 0, sizeof(symbols)); 1.1118 + uprv_memset(&symbolNames, 0, sizeof(symbolNames)); 1.1119 + 1.1120 + /* write the linker export directive */ 1.1121 + uprv_strcpy(objHeader.linkerOptions, "-export:"); 1.1122 + length=8; 1.1123 + uprv_strcpy(objHeader.linkerOptions+length, entry); 1.1124 + length+=entryLength; 1.1125 + uprv_strcpy(objHeader.linkerOptions+length, ",data "); 1.1126 + length+=6; 1.1127 + 1.1128 + /* set the file header */ 1.1129 + objHeader.fileHeader.Machine=cpu; 1.1130 + objHeader.fileHeader.NumberOfSections=2; 1.1131 + objHeader.fileHeader.TimeDateStamp=(DWORD)time(NULL); 1.1132 + objHeader.fileHeader.PointerToSymbolTable=IMAGE_SIZEOF_FILE_HEADER+2*IMAGE_SIZEOF_SECTION_HEADER+length+size; /* start of symbol table */ 1.1133 + objHeader.fileHeader.NumberOfSymbols=1; 1.1134 + 1.1135 + /* set the section for the linker options */ 1.1136 + uprv_strncpy((char *)objHeader.sections[0].Name, ".drectve", 8); 1.1137 + objHeader.sections[0].SizeOfRawData=length; 1.1138 + objHeader.sections[0].PointerToRawData=IMAGE_SIZEOF_FILE_HEADER+2*IMAGE_SIZEOF_SECTION_HEADER; 1.1139 + objHeader.sections[0].Characteristics=IMAGE_SCN_LNK_INFO|IMAGE_SCN_LNK_REMOVE|IMAGE_SCN_ALIGN_1BYTES; 1.1140 + 1.1141 + /* set the data section */ 1.1142 + uprv_strncpy((char *)objHeader.sections[1].Name, ".rdata", 6); 1.1143 + objHeader.sections[1].SizeOfRawData=size; 1.1144 + objHeader.sections[1].PointerToRawData=IMAGE_SIZEOF_FILE_HEADER+2*IMAGE_SIZEOF_SECTION_HEADER+length; 1.1145 + objHeader.sections[1].Characteristics=IMAGE_SCN_CNT_INITIALIZED_DATA|IMAGE_SCN_ALIGN_16BYTES|IMAGE_SCN_MEM_READ; 1.1146 + 1.1147 + /* set the symbol table */ 1.1148 + if(entryLength<=8) { 1.1149 + uprv_strncpy((char *)symbols[0].N.ShortName, entry, entryLength); 1.1150 + symbolNames.sizeofLongNames=4; 1.1151 + } else { 1.1152 + symbols[0].N.Name.Short=0; 1.1153 + symbols[0].N.Name.Long=4; 1.1154 + symbolNames.sizeofLongNames=4+entryLength+1; 1.1155 + uprv_strcpy(symbolNames.longNames, entry); 1.1156 + } 1.1157 + symbols[0].SectionNumber=2; 1.1158 + symbols[0].StorageClass=IMAGE_SYM_CLASS_EXTERNAL; 1.1159 + 1.1160 + /* write the file header and the linker options section */ 1.1161 + T_FileStream_write(out, &objHeader, objHeader.sections[1].PointerToRawData); 1.1162 +#else 1.1163 +# error "Unknown platform for CAN_GENERATE_OBJECTS." 1.1164 +#endif 1.1165 + 1.1166 + /* copy the data file into section 2 */ 1.1167 + for(;;) { 1.1168 + length=T_FileStream_read(in, buffer, sizeof(buffer)); 1.1169 + if(length==0) { 1.1170 + break; 1.1171 + } 1.1172 + T_FileStream_write(out, buffer, (int32_t)length); 1.1173 + } 1.1174 + 1.1175 +#if U_PLATFORM_HAS_WIN32_API 1.1176 + /* write the symbol table */ 1.1177 + T_FileStream_write(out, symbols, IMAGE_SIZEOF_SYMBOL); 1.1178 + T_FileStream_write(out, &symbolNames, symbolNames.sizeofLongNames); 1.1179 +#endif 1.1180 + 1.1181 + if(T_FileStream_error(in)) { 1.1182 + fprintf(stderr, "genccode: file read error while generating from file %s\n", filename); 1.1183 + exit(U_FILE_ACCESS_ERROR); 1.1184 + } 1.1185 + 1.1186 + if(T_FileStream_error(out)) { 1.1187 + fprintf(stderr, "genccode: file write error while generating from file %s\n", filename); 1.1188 + exit(U_FILE_ACCESS_ERROR); 1.1189 + } 1.1190 + 1.1191 + T_FileStream_close(out); 1.1192 + T_FileStream_close(in); 1.1193 +} 1.1194 +#endif