Home | History | Annotate | Download | only in util
      1 #include <stdint.h>
      2 #include <stddef.h>
      3 #include <stdio.h>
      4 #include <stdlib.h>
      5 #include <unistd.h>
      6 #include <fcntl.h>
      7 #include <errno.h>
      8 #include <sys/types.h>
      9 #include <sys/stat.h>
     10 #include <sys/mman.h>
     11 #include <elf.h>
     12 #include <gpxe/tables.h>
     13 
     14 #define DEBUG 0
     15 
     16 #define eprintf(...) fprintf ( stderr, __VA_ARGS__ )
     17 
     18 #define dprintf(...) do {						\
     19 	if ( DEBUG )							\
     20 		fprintf ( stderr, __VA_ARGS__ );			\
     21 	} while ( 0 )
     22 
     23 #ifdef SELF_INCLUDED
     24 
     25 /**
     26  * Fix up ICC alignments
     27  *
     28  * @v elf		ELF header
     29  * @ret rc		Return status code
     30  *
     31  * See comments in tables.h for an explanation of why this monstrosity
     32  * is necessary.
     33  */
     34 static int ICCFIX ( void *elf ) {
     35 	ELF_EHDR *ehdr = elf;
     36 	ELF_SHDR *shdr = ( elf + ehdr->e_shoff );
     37 	size_t shentsize = ehdr->e_shentsize;
     38 	unsigned int shnum = ehdr->e_shnum;
     39 	ELF_SHDR *strtab = ( ( ( void * ) shdr ) +
     40 			     ( ehdr->e_shstrndx * shentsize ) );
     41 	char *strings = ( elf + strtab->sh_offset );
     42 
     43 	for ( ; shnum-- ; shdr = ( ( ( void * ) shdr ) + shentsize ) ) {
     44 		char *name = ( strings + shdr->sh_name );
     45 		unsigned long align = shdr->sh_addralign;
     46 		unsigned long new_align;
     47 
     48 		if ( ( strncmp ( name, ".tbl.", 5 ) == 0 ) &&
     49 		     ( align >= ICC_ALIGN_HACK_FACTOR ) ) {
     50 			new_align = ( align / ICC_ALIGN_HACK_FACTOR );
     51 			shdr->sh_addralign = new_align;
     52 			dprintf ( "Section \"%s\": alignment %d->%d\n",
     53 				  name, align, new_align );
     54 		}
     55 	}
     56 	return 0;
     57 }
     58 
     59 #else /* SELF_INCLUDED */
     60 
     61 #define SELF_INCLUDED
     62 
     63 /* Include iccfix32() function */
     64 #define ELF_EHDR Elf32_Ehdr
     65 #define ELF_SHDR Elf32_Shdr
     66 #define ICCFIX iccfix32
     67 #include "iccfix.c"
     68 #undef ELF_EHDR
     69 #undef ELF_SHDR
     70 #undef ICCFIX
     71 
     72 /* Include iccfix64() function */
     73 #define ELF_EHDR Elf64_Ehdr
     74 #define ELF_SHDR Elf64_Shdr
     75 #define ICCFIX iccfix64
     76 #include "iccfix.c"
     77 #undef ELF_EHDR
     78 #undef ELF_SHDR
     79 #undef ICCFIX
     80 
     81 static int iccfix ( const char *filename ) {
     82 	int fd;
     83 	struct stat stat;
     84 	void *elf;
     85 	unsigned char *eident;
     86 	int rc;
     87 
     88 	/* Open and mmap file */
     89 	fd = open ( filename, O_RDWR );
     90 	if ( fd < 0 ) {
     91 		eprintf ( "Could not open %s: %s\n",
     92 			  filename, strerror ( errno ) );
     93 		rc = -1;
     94 		goto err_open;
     95 	}
     96 	if ( fstat ( fd, &stat ) < 0 ) {
     97 		eprintf ( "Could not determine size of %s: %s\n",
     98 			  filename, strerror ( errno ) );
     99 		rc = -1;
    100 		goto err_fstat;
    101 	}
    102 	elf = mmap ( NULL, stat.st_size, ( PROT_READ | PROT_WRITE ),
    103 		     MAP_SHARED, fd, 0 );
    104 	if ( elf == MAP_FAILED ) {
    105 		eprintf ( "Could not map %s: %s\n",
    106 			  filename, strerror ( errno ) );
    107 		rc = -1;
    108 		goto err_mmap;
    109 	}
    110 
    111 	/* Perform fixups */
    112 	eident = elf;
    113 	switch ( eident[EI_CLASS] ) {
    114 	case ELFCLASS32:
    115 		rc = iccfix32 ( elf );
    116 		break;
    117 	case ELFCLASS64:
    118 		rc = iccfix64 ( elf );
    119 		break;
    120 	default:
    121 		eprintf ( "Unknown ELF class %d in %s\n",
    122 			  eident[EI_CLASS], filename );
    123 		rc = -1;
    124 		break;
    125 	}
    126 
    127 	munmap ( elf, stat.st_size );
    128  err_mmap:
    129  err_fstat:
    130 	close ( fd );
    131  err_open:
    132 	return rc;
    133 }
    134 
    135 int main ( int argc, char **argv ) {
    136 	int i;
    137 	int rc;
    138 
    139 	/* Parse command line */
    140 	if ( argc < 2 ) {
    141 		eprintf ( "Syntax: %s <object_file>...\n", argv[0] );
    142 		exit ( 1 );
    143 	}
    144 
    145 	/* Process each object in turn */
    146 	for ( i = 1 ; i < argc ; i++ ) {
    147 		if ( ( rc = iccfix ( argv[i] ) ) != 0 ) {
    148 			eprintf ( "Could not fix up %s\n", argv[i] );
    149 			exit ( 1 );
    150 		}
    151 	}
    152 
    153 	return 0;
    154 }
    155 
    156 #endif /* SELF_INCLUDED */
    157