Mercurial > hg > CbC > CbC_gcc
diff gcc/lto/lto-coff.h @ 63:b7f97abdc517 gcc-4.6-20100522
update gcc from gcc-4.5.0 to gcc-4.6
author | ryoma <e075725@ie.u-ryukyu.ac.jp> |
---|---|
date | Mon, 24 May 2010 12:47:05 +0900 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gcc/lto/lto-coff.h Mon May 24 12:47:05 2010 +0900 @@ -0,0 +1,408 @@ +/* LTO routines for COFF object files. + Copyright 2009 Free Software Foundation, Inc. + Contributed by Dave Korn. + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 3, or (at your option) any later +version. + +GCC is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with GCC; see the file COPYING3. If not see +<http://www.gnu.org/licenses/>. */ + +#ifndef LTO_COFF_H +#define LTO_COFF_H + +/* Rather than implementing a libcoff to match libelf, or attempting to + integrate libbfd into GCC, this file is a self-contained (and very + minimal) COFF format object file reader/writer. The generated files + will contain a COFF header, a number of COFF section headers, the + section data itself, and a trailing string table for section names. */ + +/* Alignment of sections in a COFF object file. + + The LTO writer uses zlib compression on the data that it streams into + LTO sections in the output object file. Because these streams don't + have any embedded size information, the section in the object file must + be exactly sized to the data emitted; any trailing padding bytes will + be interpreted as partial and/or corrupt compressed data. + + This is easy enough to do on COFF targets (with binutils 2.20.1 or + above) because we can specify 1-byte alignment for the LTO sections. + They are then emitted precisely-sized and byte-packed into the object + and the reader is happy when it parses them later. This is currently + implemented in the x86/windows backed in i386_pe_asm_named_section() + in config/i386/winnt.c by detecting the LTO section name prefix, + + That would be sufficient, but for one thing. At the start of the LTO + data is a header struct with (currently) a couple of version numbers and + some type info; see struct lto_header in lto-streamer.h. If the sections + are byte-packed, this header will not necessarily be correctly-aligned + when it is read back into memory. + + On x86 targets, which are currently the only LTO-COFF targets, misaligned + memory accesses aren't problematic (okay, inefficient, but not worth + worrying about two half-word memory reads per section in the context of + everything else the compiler has to do at the time!), but RISC targets may + fail on trying to access the header struct. In this case, it will be + necessary to enable (preferably in a target-dependent fashion, but a few + bytes of padding are hardly an important issue if it comes down to it) the + COFF_ALIGNMENT macros below. + + As currently implemented, this will emit padding to the necessary number + of bytes after each LTO section. These bytes will constitute 'gaps' in + the object file structure, as they won't be covered by any section header. + This hasn't yet been tested, because no such RISC LTO-COFF target yet + exists. If it causes problems further down the toolchain, it will be + necessary to adapt the code to emit additional section headers for these + padding bytes, but the odds are that it will "just work". + + */ + +#if 0 +#define COFF_ALIGNMENT (4) +#define COFF_ALIGNMENTM1 (COFF_ALIGNMENT - 1) +#define COFF_ALIGN(x) (((x) + COFF_ALIGNMENTM1) & ~COFF_ALIGNMENTM1) +#else +#define COFF_ALIGNMENT (1) +#define COFF_ALIGN(x) (x) +#endif + +/* COFF header machine codes. */ + +#define IMAGE_FILE_MACHINE_I386 (0x014c) +#define IMAGE_FILE_MACHINE_AMD64 (0x8664) + +/* Known header magics for validation, as an array initialiser. */ + +#define COFF_KNOWN_MACHINES \ + { IMAGE_FILE_MACHINE_I386, \ + IMAGE_FILE_MACHINE_AMD64/*, ... add more here when working. */ } + +/* COFF object file header, section and symbol flags and types. These are + currently specific to PE-COFF, which is the only LTO-COFF format at the + time of writing. Maintainers adding support for new COFF formats will + need to make these into target macros of some kind. */ + +/* COFF header characteristics. */ + +#define IMAGE_FILE_EXECUTABLE_IMAGE (1 << 1) +#define IMAGE_FILE_32BIT_MACHINE (1 << 8) +#define IMAGE_FILE_SYSTEM (1 << 12) +#define IMAGE_FILE_DLL (1 << 13) + +/* Desired characteristics (for validation). */ + +#define COFF_CHARACTERISTICS \ + (IMAGE_FILE_32BIT_MACHINE) + +/* Unwanted characteristics (for validation). */ + +#define COFF_NOT_CHARACTERISTICS \ + (IMAGE_FILE_EXECUTABLE_IMAGE | IMAGE_FILE_SYSTEM | IMAGE_FILE_DLL) + +/* Section flags. LTO emits byte-aligned read-only loadable data sections. */ + +#define IMAGE_SCN_CNT_INITIALIZED_DATA (1 << 6) +#define IMAGE_SCN_CNT_UNINITIALIZED_DATA (1 << 7) +#define IMAGE_SCN_ALIGN_1BYTES (0x1 << 20) +#define IMAGE_SCN_MEM_DISCARDABLE (1 << 25) +#define IMAGE_SCN_MEM_SHARED (1 << 28) +#define IMAGE_SCN_MEM_READ (1 << 30) + +#define COFF_SECTION_CHARACTERISTICS \ + (IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_ALIGN_1BYTES | \ + IMAGE_SCN_MEM_DISCARDABLE | IMAGE_SCN_MEM_SHARED | IMAGE_SCN_MEM_READ) + +/* Symbol-related constants. */ + +#define IMAGE_SYM_DEBUG (-2) +#define IMAGE_SYM_TYPE_NULL (0) +#define IMAGE_SYM_DTYPE_NULL (0) +#define IMAGE_SYM_CLASS_STATIC (3) +#define IMAGE_SYM_CLASS_FILE (103) + +#define IMAGE_SYM_TYPE \ + ((IMAGE_SYM_DTYPE_NULL << 4) | IMAGE_SYM_TYPE_NULL) + +/* Size of a COFF symbol in bytes. */ + +#define COFF_SYMBOL_SIZE (18) + +/* On-disk file structures. */ + +struct Coff_header +{ + unsigned char Machine[2]; + unsigned char NumberOfSections[2]; + unsigned char TimeDateStamp[4]; + unsigned char PointerToSymbolTable[4]; + unsigned char NumberOfSymbols[4]; + unsigned char SizeOfOptionalHeader[2]; + unsigned char Characteristics[2]; +}; +typedef struct Coff_header Coff_header; + +struct Coff_section +{ + unsigned char Name[8]; + unsigned char VirtualSize[4]; + unsigned char VirtualAddress[4]; + unsigned char SizeOfRawData[4]; + unsigned char PointerToRawData[4]; + unsigned char PointerToRelocations[4]; + unsigned char PointerToLinenumbers[4]; + unsigned char NumberOfRelocations[2]; + unsigned char NumberOfLinenumbers[2]; + unsigned char Characteristics[4]; +}; +typedef struct Coff_section Coff_section; + +struct Coff_symbol +{ + unsigned char Name[8]; + unsigned char Value[4]; + unsigned char SectionNumber[2]; + unsigned char Type[2]; + unsigned char StorageClass[1]; + unsigned char NumberOfAuxSymbols[1]; +}; +typedef struct Coff_symbol Coff_symbol; + +struct Coff_aux_sym_file +{ + unsigned char FileName[18]; +}; +typedef struct Coff_aux_sym_file Coff_aux_sym_file; + +struct Coff_aux_sym_section +{ + unsigned char Length[4]; + unsigned char NumberOfRelocations[2]; + unsigned char NumberOfLineNumbers[2]; + unsigned char Checksum[4]; + unsigned char Number[2]; + unsigned char Selection[1]; + unsigned char Unused[3]; +}; +typedef struct Coff_aux_sym_section Coff_aux_sym_section; + +/* Accessor macros for the above structures. */ + +#define COFF_GET(struc,memb) \ + ((COFFENDIAN ? get_be : get_le) (&(struc)->memb[0], sizeof ((struc)->memb))) + +#define COFF_PUT(struc,memb,val) \ + ((COFFENDIAN ? put_be : put_le) (&(struc)->memb[0], sizeof ((struc)->memb), val)) + +#define COFF_PUT_NDXSZ(struc,memb,val,ndx,sz) \ + ((COFFENDIAN ? put_be : put_le) (&(struc)->memb[ndx], sz, val)) + +/* In-memory file structures. */ + +/* Forward declared structs. */ + +struct lto_coff_data; +struct lto_coff_section; +struct lto_coff_file; + +/* Section data in output files is made of these. */ + +struct lto_coff_data +{ + /* Pointer to data block. */ + void *d_buf; + + /* Size of data block. */ + ssize_t d_size; + + /* Next data block for this section. */ + struct lto_coff_data *next; +}; +typedef struct lto_coff_data lto_coff_data; + +/* This struct tracks the data for a section. */ + +struct lto_coff_section +{ + /* Singly-linked list of section's data blocks. */ + lto_coff_data *data_chain; + + /* Offset in string table of name. */ + size_t strtab_offs; + + /* Section type: 0 = real, 1 = dummy. */ + size_t type; + + /* Section name. */ + const char *name; + +#if COFF_ALIGNMENT > 1 + /* Number of trailing padding bytes needed. */ + ssize_t pad_needed; +#endif + + /* Raw section header data. */ + Coff_section coffsec; + + /* Next section for this file. */ + struct lto_coff_section *next; +}; +typedef struct lto_coff_section lto_coff_section; + +/* A COFF file. */ + +struct lto_coff_file +{ + /* The base information. */ + lto_file base; + + /* Common file members: */ + + /* The system file descriptor for the file. */ + int fd; + + /* The file's overall header. */ + Coff_header coffhdr; + + /* All sections in a singly-linked list. */ + lto_coff_section *section_chain; + + /* Readable file members: */ + + /* File total size. */ + off_t file_size; + + /* String table file offset, relative to base.offset. */ + off_t strtab_offs; + + /* Writable file members: */ + + /* The currently active section. */ + lto_coff_section *scn; + + /* The output stream for section header names. */ + struct lto_output_stream *shstrtab_stream; + + /* Linked list of data which must be freed *after* the file has been + closed. This is an annoying limitation of libelf. Which has been + faithfully reproduced here. */ + struct lto_char_ptr_base *data; +}; +typedef struct lto_coff_file lto_coff_file; + +/* Data hunk iterator. */ + +#define COFF_FOR_ALL_DATA(sec,var) \ + for (var = sec->data_chain; var; var = var->next) + +/* Section list iterator. */ + +#define COFF_FOR_ALL_SECTIONS(file,var) \ + for (var = file->section_chain; var; var = var->next) + +/* Very simple endian-ness layer. */ + +#ifndef COFFENDIAN +#define COFFENDIAN (BYTES_BIG_ENDIAN) +#endif + +static inline unsigned int +get_2_le (const unsigned char *ptr) +{ + return ptr[0] | (ptr[1] << 8); +} + +static inline unsigned int +get_4_le (const unsigned char *ptr) +{ + return ptr[0] | (ptr[1] << 8) | (ptr[2] << 16) | (ptr[3] << 24); +} + +static inline unsigned int +get_2_be (const unsigned char *ptr) +{ + return ptr[1] | (ptr[0] << 8); +} + +static inline unsigned int +get_4_be (const unsigned char *ptr) +{ + return ptr[3] | (ptr[2] << 8) | (ptr[1] << 16) | (ptr[0] << 24); +} + +static inline unsigned int +get_be (const unsigned char *ptr, size_t size) +{ + gcc_assert (size == 4 || size == 2); + return (size == 2) ? get_2_be (ptr) : get_4_be (ptr); +} + +static inline unsigned int +get_le (const unsigned char *ptr, size_t size) +{ + gcc_assert (size == 4 || size == 2); + return (size == 2) ? get_2_le (ptr) : get_4_le (ptr); +} + +static inline void +put_2_le (unsigned char *ptr, unsigned int data) +{ + ptr[0] = data & 0xff; + ptr[1] = (data >> 8) & 0xff; +} + +static inline void +put_4_le (unsigned char *ptr, unsigned int data) +{ + ptr[0] = data & 0xff; + ptr[1] = (data >> 8) & 0xff; + ptr[2] = (data >> 16) & 0xff; + ptr[3] = (data >> 24) & 0xff; +} + +static inline void +put_2_be (unsigned char *ptr, unsigned int data) +{ + ptr[1] = data & 0xff; + ptr[0] = (data >> 8) & 0xff; +} + +static inline void +put_4_be (unsigned char *ptr, unsigned int data) +{ + ptr[3] = data & 0xff; + ptr[2] = (data >> 8) & 0xff; + ptr[1] = (data >> 16) & 0xff; + ptr[0] = (data >> 24) & 0xff; +} + +static inline void +put_le (unsigned char *ptr, size_t size, unsigned int data) +{ + gcc_assert (size == 4 || size == 2); + (void) (size == 2 ? put_2_le : put_4_le) (ptr, data); +} + +static inline void +put_be (unsigned char *ptr, size_t size, unsigned int data) +{ + gcc_assert (size == 4 || size == 2); + (void) (size == 2 ? put_2_be : put_4_be) (ptr, data); +} + +/* We use this for putting the string table size. */ + +#define COFF_PUT4(ptr, data) \ + ((COFFENDIAN ? put_4_be : put_4_le) (ptr, data)) + + +#endif /* LTO_COFF_H */