diff options
Diffstat (limited to 'contrib/syslinux-4.02/gpxe/src/util/iccfix.c')
-rw-r--r-- | contrib/syslinux-4.02/gpxe/src/util/iccfix.c | 156 |
1 files changed, 156 insertions, 0 deletions
diff --git a/contrib/syslinux-4.02/gpxe/src/util/iccfix.c b/contrib/syslinux-4.02/gpxe/src/util/iccfix.c new file mode 100644 index 0000000..303ae9c --- /dev/null +++ b/contrib/syslinux-4.02/gpxe/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 */ |