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 */ 34static 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 81static 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 135int 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