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