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 */