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