summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/Makefile3
-rw-r--r--src/Makefile.housekeeping84
-rw-r--r--src/arch/i386/Makefile19
-rw-r--r--src/arch/i386/drivers/net/undiload.c5
-rw-r--r--src/arch/i386/drivers/net/undinet.c5
-rw-r--r--src/crypto/md5.c12
-rw-r--r--src/include/compiler.h3
-rw-r--r--src/include/gpxe/efi/efi.h7
-rw-r--r--src/include/gpxe/tables.h95
-rw-r--r--src/libgcc/icc.c8
-rw-r--r--src/net/udp.c2
-rw-r--r--src/util/.gitignore1
-rw-r--r--src/util/iccfix.c156
13 files changed, 363 insertions, 37 deletions
diff --git a/src/Makefile b/src/Makefile
index 22a4586d..1693b4ac 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -22,7 +22,7 @@ ECHO := echo
PRINTF := printf
PERL := /usr/bin/perl
CC := $(CROSS_COMPILE)gcc
-CPP := $(CROSS_COMPILE)gcc -E -Wp,-Wall
+CPP := $(CC) -E
AS := $(CROSS_COMPILE)as
LD := $(CROSS_COMPILE)ld
SIZE := $(CROSS_COMPILE)size
@@ -40,6 +40,7 @@ ZBIN := ./util/zbin
ELF2EFI32 := ./util/elf2efi32
ELF2EFI64 := ./util/elf2efi64
EFIROM := ./util/efirom
+ICCFIX := ./util/iccfix
DOXYGEN := doxygen
###############################################################################
diff --git a/src/Makefile.housekeeping b/src/Makefile.housekeeping
index 2ab842e6..23ef8c60 100644
--- a/src/Makefile.housekeeping
+++ b/src/Makefile.housekeeping
@@ -62,6 +62,22 @@ hostos :
###############################################################################
#
+# Determine compiler
+
+CCDEFS := $(shell $(CC) -E -x c -c /dev/null -dM | cut -d" " -f2)
+ccdefs:
+ @$(ECHO) $(CCDEFS)
+
+ifeq ($(filter __ICC,$(CCDEFS)),__ICC)
+CCTYPE := icc
+else
+CCTYPE := gcc
+endif
+cctype:
+ @$(ECHO) $(CCTYPE)
+
+###############################################################################
+#
# Check for tools that can cause failed builds
#
.toolcheck :
@@ -103,10 +119,12 @@ oldgas :
# default, even when -ffreestanding is specified. We therefore need
# to disable -fstack-protector if the compiler supports it.
#
+ifeq ($(CCTYPE),gcc)
SP_TEST = $(CC) -fno-stack-protector -x c -c /dev/null \
-o /dev/null >/dev/null 2>&1
SP_FLAGS := $(shell $(SP_TEST) && $(ECHO) '-fno-stack-protector')
CFLAGS += $(SP_FLAGS)
+endif
###############################################################################
#
@@ -279,9 +297,38 @@ ifdef BIN
# Common flags
#
CFLAGS += -I include -I arch/$(ARCH)/include -I .
-CFLAGS += -Os -ffreestanding
-CFLAGS += -Wall -W -Wformat-nonliteral
+CFLAGS += -Os
CFLAGS += -g
+ifeq ($(CCTYPE),gcc)
+CFLAGS += -ffreestanding
+CFLAGS += -Wall -W -Wformat-nonliteral
+endif
+ifeq ($(CCTYPE),icc)
+CFLAGS += -fno-builtin
+CFLAGS += -no-ip
+CFLAGS += -no-gcc
+CFLAGS += -diag-disable 111 # Unreachable code
+CFLAGS += -diag-disable 128 # Unreachable loop
+CFLAGS += -diag-disable 170 # Array boundary checks
+CFLAGS += -diag-disable 177 # Unused functions
+CFLAGS += -diag-disable 181 # printf() format checks
+CFLAGS += -diag-disable 188 # enum strictness
+CFLAGS += -diag-disable 193 # Undefined preprocessor identifiers
+CFLAGS += -diag-disable 280 # switch ( constant )
+CFLAGS += -diag-disable 310 # K&R parameter lists
+CFLAGS += -diag-disable 424 # Extra semicolon
+CFLAGS += -diag-disable 589 # Declarations mid-code
+CFLAGS += -diag-disable 593 # Unused variables
+CFLAGS += -diag-disable 810 # Casting ints to smaller ints
+CFLAGS += -diag-disable 981 # Sequence point violations
+CFLAGS += -diag-disable 1292 # Ignored attributes
+CFLAGS += -diag-disable 1338 # void pointer arithmetic
+CFLAGS += -diag-disable 1361 # Variable-length arrays
+CFLAGS += -diag-disable 1418 # Missing prototypes
+CFLAGS += -diag-disable 1419 # Missing prototypes
+CFLAGS += -diag-disable 1599 # Hidden variables
+CFLAGS += -Wall -Wmissing-declarations
+endif
CFLAGS += $(EXTRA_CFLAGS)
ASFLAGS += $(EXTRA_ASFLAGS)
LDFLAGS += $(EXTRA_LDFLAGS)
@@ -314,11 +361,21 @@ OBJ_CFLAGS = $(CFLAGS_$(OBJECT)) -DOBJECT=$(subst -,_,$(OBJECT))
$(BIN)/%.flags :
@$(ECHO) $(OBJ_CFLAGS)
+# ICC requires postprocessing objects to fix up table alignments
+#
+ifeq ($(CCTYPE),icc)
+POST_O = && $(ICCFIX) $@
+POST_O_DEPS := $(ICCFIX)
+else
+POST_O :=
+POST_O_DEPS :=
+endif
+
# Rules for specific object types.
#
COMPILE_c = $(CC) $(CFLAGS) $(CFLAGS_c) $(OBJ_CFLAGS)
-RULE_c = $(Q)$(COMPILE_c) -c $< -o $@
-RULE_c_to_dbg%.o = $(Q)$(COMPILE_c) -Ddebug_$(OBJECT)=$* -c $< -o $@
+RULE_c = $(Q)$(COMPILE_c) -c $< -o $@ $(POST_O)
+RULE_c_to_dbg%.o = $(Q)$(COMPILE_c) -Ddebug_$(OBJECT)=$* -c $< -o $@ $(POST_O)
RULE_c_to_c = $(Q)$(COMPILE_c) -E -c $< > $@
RULE_c_to_s = $(Q)$(COMPILE_c) -S -g0 -c $< -o $@
@@ -364,15 +421,17 @@ endef
define obj_template
@$(CPP) $(CFLAGS) $(CFLAGS_$(3)) $(CFLAGS_$(4)) -DOBJECT=$(4) \
- -Wno-error -MM $(1) -MT "$(4)_DEPS" -MG -MP | \
- sed 's/_DEPS\s*:/_DEPS =/' >> $(2)
- @$(ECHO_E) '\n$$(BIN)/$(4).o : $(1) $$(MAKEDEPS) $$($(4)_DEPS)' \
+ -Wno-error -MM $(1) -MG -MP | \
+ sed 's/\.o\s*:/_DEPS =/' >> $(2)
+ @$(ECHO_E) '\n$$(BIN)/$(4).o :' \
+ '$(1) $$(MAKEDEPS) $$(POST_O_DEPS) $$($(4)_DEPS)' \
'\n\t$$(QM)$(ECHO) " [BUILD] $$@"' \
'\n\t$$(RULE_$(3))\n' \
'\nBOBJS += $$(BIN)/$(4).o\n' \
$(foreach TGT,$(DEBUG_TARGETS), \
$(if $(RULE_$(3)_to_$(TGT)), \
- '\n$$(BIN)/$(4).$(TGT) : $(1) $$(MAKEDEPS) $$($(4)_DEPS)' \
+ '\n$$(BIN)/$(4).$(TGT) :' \
+ '$(1) $$(MAKEDEPS) $$(POST_O_DEPS) $$($(4)_DEPS)' \
'\n\t$$(QM)$(ECHO) " [BUILD] $$@"' \
'\n\t$$(RULE_$(3)_to_$(TGT))\n' \
'\n$(TGT)_OBJS += $$(BIN)/$(4).$(TGT)\n' ) ) \
@@ -745,6 +804,15 @@ CLEANUP += $(EFIROM)
###############################################################################
#
+# The ICC fixup utility
+#
+$(ICCFIX) : util/iccfix.c $(MAKEDEPS)
+ $(QM)$(ECHO) " [HOSTCC] $@"
+ $(Q)$(HOST_CC) -idirafter include -O2 -o $@ $<
+CLEANUP += $(ICCFIX)
+
+###############################################################################
+#
# Auto-incrementing build serial number. Append "bs" to your list of
# build targets to get a serial number printed at the end of the
# build. Enable -DBUILD_SERIAL in order to see it when the code runs.
diff --git a/src/arch/i386/Makefile b/src/arch/i386/Makefile
index 1392bbac..ca8ba1b2 100644
--- a/src/arch/i386/Makefile
+++ b/src/arch/i386/Makefile
@@ -4,22 +4,33 @@ CFLAGS += -march=i386
# Code size reduction.
#
-CFLAGS += -fstrength-reduce -fomit-frame-pointer
+CFLAGS += -fomit-frame-pointer
+
+# Code size reduction.
+#
+ifeq ($(CCTYPE),gcc)
+CFLAGS += -fstrength-reduce
+endif
# Code size reduction. gcc3 needs a different syntax to gcc2 if you
# want to avoid spurious warnings.
#
+ifeq ($(CCTYPE),gcc)
GCC_VERSION := $(subst ., ,$(shell $(CC) -dumpversion))
GCC_MAJOR := $(firstword $(GCC_VERSION))
ifeq ($(GCC_MAJOR),2)
CFLAGS += -malign-jumps=1 -malign-loops=1 -malign-functions=1
else
CFLAGS += -falign-jumps=1 -falign-loops=1 -falign-functions=1
-endif
+endif # gcc2
+endif # gcc
-# Code size reduction. This is almost always a win. The kernel uses it, too.
+# Code size reduction. This is almost always a win. The kernel uses
+# it, too.
#
+ifeq ($(CCTYPE),gcc)
CFLAGS += -mpreferred-stack-boundary=2
+endif
# Code size reduction. Use regparm for all functions - C functions
# called from assembly (or vice versa) need __asmcall now
@@ -27,7 +38,9 @@ CFLAGS += -mpreferred-stack-boundary=2
CFLAGS += -mregparm=3
# Code size reduction. Use -mrtd (same __asmcall requirements as above)
+ifeq ($(CCTYPE),gcc)
CFLAGS += -mrtd
+endif
# Code size reduction. This is the logical complement to -mregparm=3.
# It doesn't currently buy us anything, but if anything ever tries to
diff --git a/src/arch/i386/drivers/net/undiload.c b/src/arch/i386/drivers/net/undiload.c
index dbd9e7c2..6f34404b 100644
--- a/src/arch/i386/drivers/net/undiload.c
+++ b/src/arch/i386/drivers/net/undiload.c
@@ -90,11 +90,10 @@ int undi_load ( struct undi_device *undi, struct undi_rom *undirom ) {
undi_loader_entry = undirom->loader_entry;
__asm__ __volatile__ ( REAL_CODE ( "pushw %%ds\n\t"
"pushw %%ax\n\t"
- "lcall *%c2\n\t"
+ "lcall *undi_loader_entry\n\t"
"addw $4, %%sp\n\t" )
: "=a" ( exit )
- : "a" ( __from_data16 ( &undi_loader ) ),
- "p" ( __from_data16 ( &undi_loader_entry ) )
+ : "a" ( __from_data16 ( &undi_loader ) )
: "ebx", "ecx", "edx", "esi", "edi", "ebp" );
/* UNDI API calls may rudely change the status of A20 and not
diff --git a/src/arch/i386/drivers/net/undinet.c b/src/arch/i386/drivers/net/undinet.c
index d6db6f7c..708fc274 100644
--- a/src/arch/i386/drivers/net/undinet.c
+++ b/src/arch/i386/drivers/net/undinet.c
@@ -173,12 +173,11 @@ static int undinet_call ( struct undi_nic *undinic, unsigned int function,
__asm__ __volatile__ ( REAL_CODE ( "pushw %%es\n\t"
"pushw %%di\n\t"
"pushw %%bx\n\t"
- "lcall *%c3\n\t"
+ "lcall *undinet_entry_point\n\t"
"addw $6, %%sp\n\t" )
: "=a" ( exit ), "=b" ( discard_b ),
"=D" ( discard_D )
- : "p" ( __from_data16 ( &undinet_entry_point )),
- "b" ( function ),
+ : "b" ( function ),
"D" ( __from_data16 ( &undinet_params ) )
: "ecx", "edx", "esi", "ebp" );
diff --git a/src/crypto/md5.c b/src/crypto/md5.c
index 76fb8a69..72b291ac 100644
--- a/src/crypto/md5.c
+++ b/src/crypto/md5.c
@@ -26,30 +26,28 @@
#include <gpxe/crypto.h>
#include <gpxe/md5.h>
-#define __md5step __attribute__ (( regparm ( 3 ) ))
-
struct md5_step {
- u32 __md5step ( * f ) ( u32 b, u32 c, u32 d );
+ u32 ( * f ) ( u32 b, u32 c, u32 d );
u8 coefficient;
u8 constant;
};
-static u32 __md5step f1(u32 b, u32 c, u32 d)
+static u32 f1(u32 b, u32 c, u32 d)
{
return ( d ^ ( b & ( c ^ d ) ) );
}
-static u32 __md5step f2(u32 b, u32 c, u32 d)
+static u32 f2(u32 b, u32 c, u32 d)
{
return ( c ^ ( d & ( b ^ c ) ) );
}
-static u32 __md5step f3(u32 b, u32 c, u32 d)
+static u32 f3(u32 b, u32 c, u32 d)
{
return ( b ^ c ^ d );
}
-static u32 __md5step f4(u32 b, u32 c, u32 d)
+static u32 f4(u32 b, u32 c, u32 d)
{
return ( c ^ ( b | ~d ) );
}
diff --git a/src/include/compiler.h b/src/include/compiler.h
index 889c2404..be3ce46f 100644
--- a/src/include/compiler.h
+++ b/src/include/compiler.h
@@ -212,7 +212,8 @@ int __debug_disable;
* @v len Length of data
*/
#define DBG_HD_IF( level, data, len ) do { \
- DBG_HDA_IF ( level, data, data, len ); \
+ const void *_data = data; \
+ DBG_HDA_IF ( level, _data, _data, len ); \
} while ( 0 )
/**
diff --git a/src/include/gpxe/efi/efi.h b/src/include/gpxe/efi/efi.h
index 1f5b8856..a71a29e2 100644
--- a/src/include/gpxe/efi/efi.h
+++ b/src/include/gpxe/efi/efi.h
@@ -31,6 +31,11 @@
/* EFI headers rudely redefine NULL */
#undef NULL
+/* EFI headers expect ICC to define __GNUC__ */
+#if defined ( __ICC ) && ! defined ( __GNUC__ )
+#define __GNUC__ 1
+#endif
+
/* Include the top-level EFI header files */
#include <gpxe/efi/Uefi.h>
#include <gpxe/efi/PiDxe.h>
@@ -69,7 +74,7 @@ struct efi_protocol {
struct efi_protocol __ ## _protocol __efi_protocol = { \
.u.guid = _protocol ## _GUID, \
.protocol = ( ( void ** ) ( void * ) \
- ( ( (_ptr) == ( ( _protocol ** ) NULL ) ) ? \
+ ( ( (_ptr) == ( ( _protocol ** ) (_ptr) ) ) ? \
(_ptr) : (_ptr) ) ), \
}
diff --git a/src/include/gpxe/tables.h b/src/include/gpxe/tables.h
index a0b6f113..39b4777f 100644
--- a/src/include/gpxe/tables.h
+++ b/src/include/gpxe/tables.h
@@ -234,10 +234,22 @@
* @endcode
*/
#define __table_entry( table, idx ) \
- __attribute__ (( __section__ ( __table_section ( table, idx ) ) \
+ __attribute__ (( __section__ ( __table_section ( table, idx ) ),\
__aligned__ ( __table_alignment ( table ) ) ))
/**
+ * Get start of linker table entries
+ *
+ * @v table Linker table
+ * @v idx Sub-table index
+ * @ret entries Start of entries
+ */
+#define __table_entries( table, idx ) ( { \
+ static __table_type ( table ) __table_entries[0] \
+ __table_entry ( table, idx ); \
+ __table_entries; } )
+
+/**
* Get start of linker table
*
* @v table Linker table
@@ -253,10 +265,7 @@
*
* @endcode
*/
-#define table_start( table ) ( { \
- static __table_type ( table ) __table_start[0] \
- __table_entry ( table, 00 ); \
- __table_start; } )
+#define table_start( table ) __table_entries ( table, 00 )
/**
* Get end of linker table
@@ -274,10 +283,7 @@
*
* @endcode
*/
-#define table_end( table ) ( { \
- static __table_type ( table ) __table_end[0] \
- __table_entry ( table, 99 ); \
- __table_end; } )
+#define table_end( table ) __table_entries ( table, 99 )
/**
* Get number of entries in linker table
@@ -352,4 +358,75 @@
pointer >= table_start ( table ) ; \
pointer-- )
+/******************************************************************************
+ *
+ * Intel's C compiler chokes on several of the constructs used in this
+ * file. The workarounds are ugly, so we use them only for an icc
+ * build.
+ *
+ */
+#define ICC_ALIGN_HACK_FACTOR 128
+#ifdef __ICC
+
+/*
+ * icc miscompiles zero-length arrays by inserting padding to a length
+ * of two array elements. We therefore have to generate the
+ * __table_entries() symbols by hand in asm.
+ *
+ */
+#undef __table_entries
+#define __table_entries( table, idx ) ( { \
+ extern __table_type ( table ) \
+ __table_temp_sym ( idx, __LINE__ ) [] \
+ __table_entry ( table, idx ) \
+ asm ( __table_entries_sym ( table, idx ) ); \
+ __asm__ ( ".ifndef %c0\n\t" \
+ ".section " __table_section ( table, idx ) "\n\t" \
+ ".align %c1\n\t" \
+ "\n%c0:\n\t" \
+ ".previous\n\t" \
+ ".endif\n\t" \
+ : : "i" ( __table_temp_sym ( idx, __LINE__ ) ), \
+ "i" ( __table_alignment ( table ) ) ); \
+ __table_temp_sym ( idx, __LINE__ ); } )
+#define __table_entries_sym( table, idx ) \
+ "__tbl_" __table_name ( table ) "_" #idx
+#define __table_temp_sym( a, b ) \
+ ___table_temp_sym( __table_, a, _, b )
+#define ___table_temp_sym( a, b, c, d ) a ## b ## c ## d
+
+/*
+ * icc ignores __attribute__ (( aligned (x) )) when it is used to
+ * decrease the compiler's default choice of alignment (which may be
+ * higher than the alignment actually required by the structure). We
+ * work around this by forcing the alignment to a large multiple of
+ * the required value (so that we are never attempting to decrease the
+ * default alignment) and then postprocessing the object file to
+ * reduce the alignment back down to the "real" value.
+ *
+ */
+#undef __table_alignment
+#define __table_alignment( table ) \
+ ( ICC_ALIGN_HACK_FACTOR * __alignof__ ( __table_type ( table ) ) )
+
+/*
+ * Because of the alignment hack, we must ensure that the compiler
+ * never tries to place multiple objects within the same section,
+ * otherwise the assembler will insert padding to the (incorrect)
+ * alignment boundary. Do this by appending the line number to table
+ * section names.
+ *
+ * Note that we don't need to worry about padding between array
+ * elements, since the alignment is declared on the variable (i.e. the
+ * whole array) rather than on the type (i.e. on all individual array
+ * elements).
+ */
+#undef __table_section
+#define __table_section( table, idx ) \
+ ".tbl." __table_name ( table ) "." __table_str ( idx ) \
+ "." __table_xstr ( __LINE__ )
+#define __table_xstr( x ) __table_str ( x )
+
+#endif /* __ICC */
+
#endif /* _GPXE_TABLES_H */
diff --git a/src/libgcc/icc.c b/src/libgcc/icc.c
new file mode 100644
index 00000000..7540bf0e
--- /dev/null
+++ b/src/libgcc/icc.c
@@ -0,0 +1,8 @@
+/*
+ * Intel's compiler creates an implicit call to this function at the
+ * start of main().
+ *
+ */
+void __attribute__ (( cdecl )) __intel_new_proc_init ( void ) {
+ /* Do nothing */
+}
diff --git a/src/net/udp.c b/src/net/udp.c
index c3a1eba3..1b83518e 100644
--- a/src/net/udp.c
+++ b/src/net/udp.c
@@ -238,7 +238,7 @@ static int udp_tx ( struct udp_connection *udp, struct io_buffer *iobuf,
* @ret udp UDP connection, or NULL
*/
static struct udp_connection * udp_demux ( struct sockaddr_tcpip *local ) {
- static const struct sockaddr_tcpip empty_sockaddr;
+ static const struct sockaddr_tcpip empty_sockaddr = { .pad = { 0, } };
struct udp_connection *udp;
list_for_each_entry ( udp, &udp_conns, list ) {
diff --git a/src/util/.gitignore b/src/util/.gitignore
index c2567012..a3752470 100644
--- a/src/util/.gitignore
+++ b/src/util/.gitignore
@@ -5,3 +5,4 @@ prototester
elf2efi32
elf2efi64
efirom
+iccfix
diff --git a/src/util/iccfix.c b/src/util/iccfix.c
new file mode 100644
index 00000000..303ae9ca
--- /dev/null
+++ b/src/util/iccfix.c
@@ -0,0 +1,156 @@
+#include <stdint.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <elf.h>
+#include <gpxe/tables.h>
+
+#define DEBUG 0
+
+#define eprintf(...) fprintf ( stderr, __VA_ARGS__ )
+
+#define dprintf(...) do { \
+ if ( DEBUG ) \
+ fprintf ( stderr, __VA_ARGS__ ); \
+ } while ( 0 )
+
+#ifdef SELF_INCLUDED
+
+/**
+ * Fix up ICC alignments
+ *
+ * @v elf ELF header
+ * @ret rc Return status code
+ *
+ * See comments in tables.h for an explanation of why this monstrosity
+ * is necessary.
+ */
+static int ICCFIX ( void *elf ) {
+ ELF_EHDR *ehdr = elf;
+ ELF_SHDR *shdr = ( elf + ehdr->e_shoff );
+ size_t shentsize = ehdr->e_shentsize;
+ unsigned int shnum = ehdr->e_shnum;
+ ELF_SHDR *strtab = ( ( ( void * ) shdr ) +
+ ( ehdr->e_shstrndx * shentsize ) );
+ char *strings = ( elf + strtab->sh_offset );
+
+ for ( ; shnum-- ; shdr = ( ( ( void * ) shdr ) + shentsize ) ) {
+ char *name = ( strings + shdr->sh_name );
+ unsigned long align = shdr->sh_addralign;
+ unsigned long new_align;
+
+ if ( ( strncmp ( name, ".tbl.", 5 ) == 0 ) &&
+ ( align >= ICC_ALIGN_HACK_FACTOR ) ) {
+ new_align = ( align / ICC_ALIGN_HACK_FACTOR );
+ shdr->sh_addralign = new_align;
+ dprintf ( "Section \"%s\": alignment %d->%d\n",
+ name, align, new_align );
+ }
+ }
+ return 0;
+}
+
+#else /* SELF_INCLUDED */
+
+#define SELF_INCLUDED
+
+/* Include iccfix32() function */
+#define ELF_EHDR Elf32_Ehdr
+#define ELF_SHDR Elf32_Shdr
+#define ICCFIX iccfix32
+#include "iccfix.c"
+#undef ELF_EHDR
+#undef ELF_SHDR
+#undef ICCFIX
+
+/* Include iccfix64() function */
+#define ELF_EHDR Elf64_Ehdr
+#define ELF_SHDR Elf64_Shdr
+#define ICCFIX iccfix64
+#include "iccfix.c"
+#undef ELF_EHDR
+#undef ELF_SHDR
+#undef ICCFIX
+
+static int iccfix ( const char *filename ) {
+ int fd;
+ struct stat stat;
+ void *elf;
+ unsigned char *eident;
+ int rc;
+
+ /* Open and mmap file */
+ fd = open ( filename, O_RDWR );
+ if ( fd < 0 ) {
+ eprintf ( "Could not open %s: %s\n",
+ filename, strerror ( errno ) );
+ rc = -1;
+ goto err_open;
+ }
+ if ( fstat ( fd, &stat ) < 0 ) {
+ eprintf ( "Could not determine size of %s: %s\n",
+ filename, strerror ( errno ) );
+ rc = -1;
+ goto err_fstat;
+ }
+ elf = mmap ( NULL, stat.st_size, ( PROT_READ | PROT_WRITE ),
+ MAP_SHARED, fd, 0 );
+ if ( elf == MAP_FAILED ) {
+ eprintf ( "Could not map %s: %s\n",
+ filename, strerror ( errno ) );
+ rc = -1;
+ goto err_mmap;
+ }
+
+ /* Perform fixups */
+ eident = elf;
+ switch ( eident[EI_CLASS] ) {
+ case ELFCLASS32:
+ rc = iccfix32 ( elf );
+ break;
+ case ELFCLASS64:
+ rc = iccfix64 ( elf );
+ break;
+ default:
+ eprintf ( "Unknown ELF class %d in %s\n",
+ eident[EI_CLASS], filename );
+ rc = -1;
+ break;
+ }
+
+ munmap ( elf, stat.st_size );
+ err_mmap:
+ err_fstat:
+ close ( fd );
+ err_open:
+ return rc;
+}
+
+int main ( int argc, char **argv ) {
+ int i;
+ int rc;
+
+ /* Parse command line */
+ if ( argc < 2 ) {
+ eprintf ( "Syntax: %s <object_file>...\n", argv[0] );
+ exit ( 1 );
+ }
+
+ /* Process each object in turn */
+ for ( i = 1 ; i < argc ; i++ ) {
+ if ( ( rc = iccfix ( argv[i] ) ) != 0 ) {
+ eprintf ( "Could not fix up %s\n", argv[i] );
+ exit ( 1 );
+ }
+ }
+
+ return 0;
+}
+
+#endif /* SELF_INCLUDED */