Browse Source

[efi] Eliminate use of libbfd

Parse the intermediate ELF file directly instead of using libbfd, in
order to allow for cross-compiled ELF objects.

As a side bonus, this eliminates libbfd as a build requirement.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown 8 years ago
parent
commit
efd5cf9aad
3 changed files with 298 additions and 177 deletions
  1. 0
    2
      src/Makefile
  2. 4
    6
      src/Makefile.housekeeping
  3. 294
    169
      src/util/elf2efi.c

+ 0
- 2
src/Makefile View File

53
 GENKEYMAP	:= ./util/genkeymap.pl
53
 GENKEYMAP	:= ./util/genkeymap.pl
54
 DOXYGEN		:= doxygen
54
 DOXYGEN		:= doxygen
55
 LCAB		:= lcab
55
 LCAB		:= lcab
56
-BINUTILS_DIR	:= /usr
57
-BFD_DIR		:= $(BINUTILS_DIR)
58
 ZLIB_DIR	:= /usr
56
 ZLIB_DIR	:= /usr
59
 
57
 
60
 ###############################################################################
58
 ###############################################################################

+ 4
- 6
src/Makefile.housekeeping View File

1303
 #
1303
 #
1304
 # The EFI image converter
1304
 # The EFI image converter
1305
 #
1305
 #
1306
-ELF2EFI_CFLAGS	:= -I$(BINUTILS_DIR)/include -I$(BFD_DIR)/include \
1307
-		   -I$(ZLIB_DIR)/include -idirafter include
1308
-ELF2EFI_LDFLAGS	:= -L$(BINUTILS_DIR)/lib -L$(BFD_DIR)/lib -L$(ZLIB_DIR)/lib \
1309
-		   -lbfd -ldl -lz -Wl,--no-warn-search-mismatch
1306
+ELF2EFI_CFLAGS	:= -I$(ZLIB_DIR)/include -idirafter include
1307
+ELF2EFI_LDFLAGS	:= -L$(ZLIB_DIR)/lib -lz -Wl,--no-warn-search-mismatch
1310
 
1308
 
1311
 $(ELF2EFI32) : util/elf2efi.c $(MAKEDEPS)
1309
 $(ELF2EFI32) : util/elf2efi.c $(MAKEDEPS)
1312
 	$(QM)$(ECHO) "  [HOSTCC] $@"
1310
 	$(QM)$(ECHO) "  [HOSTCC] $@"
1313
-	$(Q)$(HOST_CC) $(HOST_CFLAGS) $(ELF2EFI_CFLAGS) -DEFI_TARGET_IA32 $< \
1311
+	$(Q)$(HOST_CC) $(HOST_CFLAGS) $(ELF2EFI_CFLAGS) -DEFI_TARGET32 $< \
1314
 		$(ELF2EFI_LDFLAGS) -o $@
1312
 		$(ELF2EFI_LDFLAGS) -o $@
1315
 CLEANUP += $(ELF2EFI32)
1313
 CLEANUP += $(ELF2EFI32)
1316
 
1314
 
1317
 $(ELF2EFI64) : util/elf2efi.c $(MAKEDEPS)
1315
 $(ELF2EFI64) : util/elf2efi.c $(MAKEDEPS)
1318
 	$(QM)$(ECHO) "  [HOSTCC] $@"
1316
 	$(QM)$(ECHO) "  [HOSTCC] $@"
1319
-	$(Q)$(HOST_CC) $(HOST_CFLAGS) $(ELF2EFI_CFLAGS) -DEFI_TARGET_X64 $< \
1317
+	$(Q)$(HOST_CC) $(HOST_CFLAGS) $(ELF2EFI_CFLAGS) -DEFI_TARGET64 $< \
1320
 		$(ELF2EFI_LDFLAGS) -o $@
1318
 		$(ELF2EFI_LDFLAGS) -o $@
1321
 CLEANUP += $(ELF2EFI64)
1319
 CLEANUP += $(ELF2EFI64)
1322
 
1320
 

+ 294
- 169
src/util/elf2efi.c View File

17
  * 02110-1301, USA.
17
  * 02110-1301, USA.
18
  */
18
  */
19
 
19
 
20
-#define _GNU_SOURCE
21
-#define PACKAGE "elf2efi"
22
-#define PACKAGE_VERSION "1"
23
 #define FILE_LICENCE(...) extern void __file_licence ( void )
20
 #define FILE_LICENCE(...) extern void __file_licence ( void )
24
 #include <stdint.h>
21
 #include <stdint.h>
25
 #include <stddef.h>
22
 #include <stddef.h>
30
 #include <errno.h>
27
 #include <errno.h>
31
 #include <assert.h>
28
 #include <assert.h>
32
 #include <getopt.h>
29
 #include <getopt.h>
33
-#include <bfd.h>
30
+#include <sys/types.h>
31
+#include <sys/stat.h>
32
+#include <sys/mman.h>
33
+#include <fcntl.h>
34
+#include <elf.h>
34
 #include <ipxe/efi/Uefi.h>
35
 #include <ipxe/efi/Uefi.h>
35
 #include <ipxe/efi/IndustryStandard/PeImage.h>
36
 #include <ipxe/efi/IndustryStandard/PeImage.h>
36
 #include <libgen.h>
37
 #include <libgen.h>
37
 
38
 
38
 #define eprintf(...) fprintf ( stderr, __VA_ARGS__ )
39
 #define eprintf(...) fprintf ( stderr, __VA_ARGS__ )
39
 
40
 
41
+#ifdef EFI_TARGET32
42
+
43
+#define EFI_IMAGE_NT_HEADERS		EFI_IMAGE_NT_HEADERS32
44
+#define EFI_IMAGE_NT_OPTIONAL_HDR_MAGIC	EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
45
+#define EFI_IMAGE_FILE_MACHINE		EFI_IMAGE_FILE_32BIT_MACHINE
46
+#define ELFCLASS   ELFCLASS32
47
+#define Elf_Ehdr   Elf32_Ehdr
48
+#define Elf_Shdr   Elf32_Shdr
49
+#define Elf_Sym    Elf32_Sym
50
+#define Elf_Addr   Elf32_Addr
51
+#define Elf_Rel    Elf32_Rel
52
+#define Elf_Rela   Elf32_Rela
53
+#define ELF_R_TYPE ELF32_R_TYPE
54
+#define ELF_R_SYM  ELF32_R_SYM
55
+
56
+#elif defined(EFI_TARGET64)
57
+
58
+#define EFI_IMAGE_NT_HEADERS		EFI_IMAGE_NT_HEADERS64
59
+#define EFI_IMAGE_NT_OPTIONAL_HDR_MAGIC	EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
60
+#define EFI_IMAGE_FILE_MACHINE		0
61
+#define ELFCLASS   ELFCLASS64
62
+#define Elf_Ehdr   Elf64_Ehdr
63
+#define Elf_Shdr   Elf64_Shdr
64
+#define Elf_Sym    Elf64_Sym
65
+#define Elf_Addr   Elf64_Addr
66
+#define Elf_Rel    Elf64_Rel
67
+#define Elf_Rela   Elf64_Rela
68
+#define ELF_R_TYPE ELF64_R_TYPE
69
+#define ELF_R_SYM  ELF64_R_SYM
70
+
71
+#endif
72
+
40
 #define EFI_FILE_ALIGN 0x20
73
 #define EFI_FILE_ALIGN 0x20
41
 
74
 
75
+struct elf_machine {
76
+	unsigned int pe_machine;
77
+	unsigned int r_none;
78
+	unsigned int r_abs;
79
+	unsigned int r_pcrel;
80
+};
81
+
82
+struct elf_file {
83
+	void *data;
84
+	size_t len;
85
+	const Elf_Ehdr *ehdr;
86
+	struct elf_machine *machine;
87
+};
88
+
42
 struct pe_section {
89
 struct pe_section {
43
 	struct pe_section *next;
90
 	struct pe_section *next;
44
 	EFI_IMAGE_SECTION_HEADER hdr;
91
 	EFI_IMAGE_SECTION_HEADER hdr;
57
 struct pe_header {
104
 struct pe_header {
58
 	EFI_IMAGE_DOS_HEADER dos;
105
 	EFI_IMAGE_DOS_HEADER dos;
59
 	uint8_t padding[128];
106
 	uint8_t padding[128];
60
-#if defined(EFI_TARGET_IA32)
61
-	EFI_IMAGE_NT_HEADERS32 nt;
62
-#elif defined(EFI_TARGET_X64)
63
-	EFI_IMAGE_NT_HEADERS64 nt;
64
-#endif
107
+	EFI_IMAGE_NT_HEADERS nt;
65
 };
108
 };
66
 
109
 
67
 static struct pe_header efi_pe_header = {
110
 static struct pe_header efi_pe_header = {
72
 	.nt = {
115
 	.nt = {
73
 		.Signature = EFI_IMAGE_NT_SIGNATURE,
116
 		.Signature = EFI_IMAGE_NT_SIGNATURE,
74
 		.FileHeader = {
117
 		.FileHeader = {
75
-#if defined(EFI_TARGET_IA32)
76
-			.Machine = EFI_IMAGE_MACHINE_IA32,
77
-#elif defined(EFI_TARGET_X64)
78
-			.Machine = EFI_IMAGE_MACHINE_X64,
79
-#endif
80
 			.TimeDateStamp = 0x10d1a884,
118
 			.TimeDateStamp = 0x10d1a884,
81
 			.SizeOfOptionalHeader =
119
 			.SizeOfOptionalHeader =
82
 				sizeof ( efi_pe_header.nt.OptionalHeader ),
120
 				sizeof ( efi_pe_header.nt.OptionalHeader ),
83
 			.Characteristics = ( EFI_IMAGE_FILE_DLL |
121
 			.Characteristics = ( EFI_IMAGE_FILE_DLL |
84
-#if defined(EFI_TARGET_IA32)
85
-					     EFI_IMAGE_FILE_32BIT_MACHINE |
86
-#endif
122
+					     EFI_IMAGE_FILE_MACHINE |
87
 					     EFI_IMAGE_FILE_EXECUTABLE_IMAGE ),
123
 					     EFI_IMAGE_FILE_EXECUTABLE_IMAGE ),
88
 		},
124
 		},
89
 		.OptionalHeader = {
125
 		.OptionalHeader = {
90
-#if defined(EFI_TARGET_IA32)
91
-			.Magic = EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC,
92
-#elif defined(EFI_TARGET_X64)
93
-			.Magic = EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC,
94
-#endif
126
+			.Magic = EFI_IMAGE_NT_OPTIONAL_HDR_MAGIC,
95
 			.MajorLinkerVersion = 42,
127
 			.MajorLinkerVersion = 42,
96
 			.MinorLinkerVersion = 42,
128
 			.MinorLinkerVersion = 42,
97
 			.SectionAlignment = EFI_FILE_ALIGN,
129
 			.SectionAlignment = EFI_FILE_ALIGN,
104
 	},
136
 	},
105
 };
137
 };
106
 
138
 
139
+static struct elf_machine machine_i386 = {
140
+	.pe_machine = EFI_IMAGE_MACHINE_IA32,
141
+	.r_none = R_386_NONE,
142
+	.r_abs = R_386_32,
143
+	.r_pcrel = R_386_PC32,
144
+};
145
+
146
+static struct elf_machine machine_x86_64 = {
147
+	.pe_machine = EFI_IMAGE_MACHINE_X64,
148
+	.r_none = R_X86_64_NONE,
149
+	.r_abs = R_X86_64_64,
150
+	.r_pcrel = R_X86_64_PC32,
151
+};
152
+
107
 /** Command-line options */
153
 /** Command-line options */
108
 struct options {
154
 struct options {
109
 	unsigned int subsystem;
155
 	unsigned int subsystem;
235
 }
281
 }
236
 
282
 
237
 /**
283
 /**
238
- * Open input BFD file
284
+ * Read input ELF file
239
  *
285
  *
240
- * @v filename		File name
241
- * @ret ibfd		BFD file
286
+ * @v name		File name
287
+ * @v elf		ELF file
242
  */
288
  */
243
-static bfd * open_input_bfd ( const char *filename ) {
244
-	bfd *bfd;
245
-
246
-	/* Open the file */
247
-	bfd = bfd_openr ( filename, NULL );
248
-	if ( ! bfd ) {
249
-		eprintf ( "Cannot open %s: ", filename );
250
-		bfd_perror ( NULL );
289
+static void read_elf_file ( const char *name, struct elf_file *elf ) {
290
+	static const unsigned char ident[] = {
291
+		ELFMAG0, ELFMAG1, ELFMAG2, ELFMAG3, ELFCLASS, ELFDATA2LSB
292
+	};
293
+	struct stat stat;
294
+	const Elf_Ehdr *ehdr;
295
+	const Elf_Shdr *shdr;
296
+	void *data;
297
+	size_t offset;
298
+	unsigned int i;
299
+	int fd;
300
+
301
+	/* Open file */
302
+	fd = open ( name, O_RDONLY );
303
+	if ( fd < 0 ) {
304
+		eprintf ( "Could not open %s: %s\n", name, strerror ( errno ) );
251
 		exit ( 1 );
305
 		exit ( 1 );
252
 	}
306
 	}
253
 
307
 
254
-	/* The call to bfd_check_format() must be present, otherwise
255
-	 * we get a segfault from later BFD calls.
256
-	 */
257
-	if ( ! bfd_check_format ( bfd, bfd_object ) ) {
258
-		eprintf ( "%s is not an object file: ", filename );
259
-		bfd_perror ( NULL );
308
+	/* Get file size */
309
+	if ( fstat ( fd, &stat ) < 0 ) {
310
+		eprintf ( "Could not get size of %s: %s\n",
311
+			  name, strerror ( errno ) );
260
 		exit ( 1 );
312
 		exit ( 1 );
261
 	}
313
 	}
314
+	elf->len = stat.st_size;
262
 
315
 
263
-	return bfd;
264
-}
265
-
266
-/**
267
- * Read symbol table
268
- *
269
- * @v bfd		BFD file
270
- */
271
-static asymbol ** read_symtab ( bfd *bfd ) {
272
-	long symtab_size;
273
-	asymbol **symtab;
274
-	long symcount;
275
-
276
-	/* Get symbol table size */
277
-	symtab_size = bfd_get_symtab_upper_bound ( bfd );
278
-	if ( symtab_size < 0 ) {
279
-		bfd_perror ( "Could not get symbol table upper bound" );
316
+	/* Map file */
317
+	data = mmap ( NULL, elf->len, PROT_READ, MAP_SHARED, fd, 0 );
318
+	if ( data == MAP_FAILED ) {
319
+		eprintf ( "Could not map %s: %s\n", name, strerror ( errno ) );
280
 		exit ( 1 );
320
 		exit ( 1 );
281
 	}
321
 	}
322
+	elf->data = data;
282
 
323
 
283
-	/* Allocate and read symbol table */
284
-	symtab = xmalloc ( symtab_size );
285
-	symcount = bfd_canonicalize_symtab ( bfd, symtab );
286
-	if ( symcount < 0 ) {
287
-		bfd_perror ( "Cannot read symbol table" );
324
+	/* Close file */
325
+	close ( fd );
326
+
327
+	/* Check header */
328
+	ehdr = elf->data;
329
+	if ( ( elf->len < sizeof ( *ehdr ) ) ||
330
+	     ( memcmp ( ident, ehdr->e_ident, sizeof ( ident ) ) != 0 ) ) {
331
+		eprintf ( "Invalid ELF header in %s\n", name );
288
 		exit ( 1 );
332
 		exit ( 1 );
289
 	}
333
 	}
334
+	elf->ehdr = ehdr;
335
+
336
+	/* Check section headers */
337
+	for ( i = 0 ; i < ehdr->e_shnum ; i++ ) {
338
+		offset = ( ehdr->e_shoff + ( i * ehdr->e_shentsize ) );
339
+		if ( elf->len < ( offset + sizeof ( *shdr ) ) ) {
340
+			eprintf ( "ELF section header outside file in %s\n",
341
+				  name );
342
+			exit ( 1 );
343
+		}
344
+		shdr = ( data + offset );
345
+		if ( ( shdr->sh_type != SHT_NOBITS ) &&
346
+		     ( ( elf->len < shdr->sh_offset ) ||
347
+		       ( ( ( elf->len - shdr->sh_offset ) < shdr->sh_size ) ))){
348
+			eprintf ( "ELF section %d outside file in %s\n",
349
+				  i, name );
350
+			exit ( 1 );
351
+		}
352
+		if ( shdr->sh_link >= ehdr->e_shnum ) {
353
+			eprintf ( "ELF section %d link section %d out of "
354
+				  "range\n", i, shdr->sh_link );
355
+			exit ( 1 );
356
+		}
357
+	}
290
 
358
 
291
-	return symtab;
359
+	/* Identify architecture */
360
+	switch ( ehdr->e_machine ) {
361
+	case EM_386:
362
+		elf->machine = &machine_i386;
363
+		break;
364
+	case EM_X86_64:
365
+		elf->machine = &machine_x86_64;
366
+		break;
367
+	default:
368
+		eprintf ( "Unknown ELF architecture %d\n", ehdr->e_machine );
369
+		exit ( 1 );
370
+	}
292
 }
371
 }
293
 
372
 
294
 /**
373
 /**
295
- * Read relocation table
374
+ * Get ELF string
296
  *
375
  *
297
- * @v bfd		BFD file
298
- * @v symtab		Symbol table
299
- * @v section		Section
300
- * @v symtab		Symbol table
301
- * @ret reltab		Relocation table
376
+ * @v elf		ELF file
377
+ * @v section		String table section number
378
+ * @v offset		String table offset
379
+ * @ret string		ELF string
302
  */
380
  */
303
-static arelent ** read_reltab ( bfd *bfd, asymbol **symtab,
304
-				asection *section ) {
305
-	long reltab_size;
306
-	arelent **reltab;
307
-	long numrels;
308
-
309
-	/* Get relocation table size */
310
-	reltab_size = bfd_get_reloc_upper_bound ( bfd, section );
311
-	if ( reltab_size < 0 ) {
312
-		bfd_perror ( "Could not get relocation table upper bound" );
381
+static const char * elf_string ( struct elf_file *elf, unsigned int section,
382
+				 size_t offset ) {
383
+	const Elf_Ehdr *ehdr = elf->ehdr;
384
+	const Elf_Shdr *shdr;
385
+	char *string;
386
+	char *last;
387
+
388
+	/* Locate section header */
389
+	if ( section >= ehdr->e_shnum ) {
390
+		eprintf ( "Invalid ELF string section %d\n", section );
313
 		exit ( 1 );
391
 		exit ( 1 );
314
 	}
392
 	}
393
+	shdr = ( elf->data + ehdr->e_shoff + ( section * ehdr->e_shentsize ) );
315
 
394
 
316
-	/* Allocate and read relocation table */
317
-	reltab = xmalloc ( reltab_size );
318
-	numrels = bfd_canonicalize_reloc ( bfd, section, reltab, symtab );
319
-	if ( numrels < 0 ) {
320
-		bfd_perror ( "Cannot read relocation table" );
395
+	/* Sanity check section */
396
+	if ( shdr->sh_type != SHT_STRTAB ) {
397
+		eprintf ( "ELF section %d (type %d) is not a string table\n",
398
+			  section, shdr->sh_type );
399
+		exit ( 1 );
400
+	}
401
+	last = ( elf->data + shdr->sh_offset + shdr->sh_size - 1 );
402
+	if ( *last != '\0' ) {
403
+		eprintf ( "ELF section %d is not NUL-terminated\n", section );
321
 		exit ( 1 );
404
 		exit ( 1 );
322
 	}
405
 	}
323
 
406
 
324
-	return reltab;
407
+	/* Locate string */
408
+	if ( offset >= shdr->sh_size ) {
409
+		eprintf ( "Invalid ELF string offset %zd in section %d\n",
410
+			  offset, section );
411
+		exit ( 1 );
412
+	}
413
+	string = ( elf->data + shdr->sh_offset + offset );
414
+
415
+	return string;
325
 }
416
 }
326
 
417
 
327
 /**
418
 /**
328
  * Process section
419
  * Process section
329
  *
420
  *
330
- * @v bfd		BFD file
421
+ * @v elf		ELF file
422
+ * @v shdr		ELF section header
331
  * @v pe_header		PE file header
423
  * @v pe_header		PE file header
332
- * @v section		Section
333
  * @ret new		New PE section
424
  * @ret new		New PE section
334
  */
425
  */
335
-static struct pe_section * process_section ( bfd *bfd,
336
-					     struct pe_header *pe_header,
337
-					     asection *section ) {
426
+static struct pe_section * process_section ( struct elf_file *elf,
427
+					     const Elf_Shdr *shdr,
428
+					     struct pe_header *pe_header ) {
338
 	struct pe_section *new;
429
 	struct pe_section *new;
430
+	const char *name;
339
 	size_t section_memsz;
431
 	size_t section_memsz;
340
 	size_t section_filesz;
432
 	size_t section_filesz;
341
-	unsigned long flags = bfd_get_section_flags ( bfd, section );
342
 	unsigned long code_start;
433
 	unsigned long code_start;
343
 	unsigned long code_end;
434
 	unsigned long code_end;
344
 	unsigned long data_start;
435
 	unsigned long data_start;
349
 	unsigned long *applicable_start;
440
 	unsigned long *applicable_start;
350
 	unsigned long *applicable_end;
441
 	unsigned long *applicable_end;
351
 
442
 
443
+	/* Get section name */
444
+	name = elf_string ( elf, elf->ehdr->e_shstrndx, shdr->sh_name );
445
+
352
 	/* Extract current RVA limits from file header */
446
 	/* Extract current RVA limits from file header */
353
 	code_start = pe_header->nt.OptionalHeader.BaseOfCode;
447
 	code_start = pe_header->nt.OptionalHeader.BaseOfCode;
354
 	code_end = ( code_start + pe_header->nt.OptionalHeader.SizeOfCode );
448
 	code_end = ( code_start + pe_header->nt.OptionalHeader.SizeOfCode );
355
-#if defined(EFI_TARGET_IA32)
449
+#if defined(EFI_TARGET32)
356
 	data_start = pe_header->nt.OptionalHeader.BaseOfData;
450
 	data_start = pe_header->nt.OptionalHeader.BaseOfData;
357
-#elif defined(EFI_TARGET_X64)
451
+#elif defined(EFI_TARGET64)
358
 	data_start = code_end;
452
 	data_start = code_end;
359
 #endif
453
 #endif
360
 	data_mid = ( data_start +
454
 	data_mid = ( data_start +
363
 		     pe_header->nt.OptionalHeader.SizeOfUninitializedData );
457
 		     pe_header->nt.OptionalHeader.SizeOfUninitializedData );
364
 
458
 
365
 	/* Allocate PE section */
459
 	/* Allocate PE section */
366
-	section_memsz = bfd_section_size ( bfd, section );
367
-	section_filesz = ( ( flags & SEC_LOAD ) ?
460
+	section_memsz = shdr->sh_size;
461
+	section_filesz = ( ( shdr->sh_type == SHT_PROGBITS ) ?
368
 			   efi_file_align ( section_memsz ) : 0 );
462
 			   efi_file_align ( section_memsz ) : 0 );
369
 	new = xmalloc ( sizeof ( *new ) + section_filesz );
463
 	new = xmalloc ( sizeof ( *new ) + section_filesz );
370
 	memset ( new, 0, sizeof ( *new ) + section_filesz );
464
 	memset ( new, 0, sizeof ( *new ) + section_filesz );
371
 
465
 
372
 	/* Fill in section header details */
466
 	/* Fill in section header details */
373
-	strncpy ( ( char * ) new->hdr.Name, section->name,
374
-		  sizeof ( new->hdr.Name ) );
467
+	strncpy ( ( char * ) new->hdr.Name, name, sizeof ( new->hdr.Name ) );
375
 	new->hdr.Misc.VirtualSize = section_memsz;
468
 	new->hdr.Misc.VirtualSize = section_memsz;
376
-	new->hdr.VirtualAddress = bfd_get_section_vma ( bfd, section );
469
+	new->hdr.VirtualAddress = shdr->sh_addr;
377
 	new->hdr.SizeOfRawData = section_filesz;
470
 	new->hdr.SizeOfRawData = section_filesz;
378
 
471
 
379
 	/* Fill in section characteristics and update RVA limits */
472
 	/* Fill in section characteristics and update RVA limits */
380
-	if ( flags & SEC_CODE ) {
473
+	if ( ( shdr->sh_type == SHT_PROGBITS ) &&
474
+	     ( shdr->sh_flags & SHF_EXECINSTR ) ) {
381
 		/* .text-type section */
475
 		/* .text-type section */
382
 		new->hdr.Characteristics =
476
 		new->hdr.Characteristics =
383
 			( EFI_IMAGE_SCN_CNT_CODE |
477
 			( EFI_IMAGE_SCN_CNT_CODE |
386
 			  EFI_IMAGE_SCN_MEM_READ );
480
 			  EFI_IMAGE_SCN_MEM_READ );
387
 		applicable_start = &code_start;
481
 		applicable_start = &code_start;
388
 		applicable_end = &code_end;
482
 		applicable_end = &code_end;
389
-	} else if ( flags & SEC_DATA ) {
483
+	} else if ( ( shdr->sh_type == SHT_PROGBITS ) &&
484
+		    ( shdr->sh_flags & SHF_WRITE ) ) {
390
 		/* .data-type section */
485
 		/* .data-type section */
391
 		new->hdr.Characteristics =
486
 		new->hdr.Characteristics =
392
 			( EFI_IMAGE_SCN_CNT_INITIALIZED_DATA |
487
 			( EFI_IMAGE_SCN_CNT_INITIALIZED_DATA |
395
 			  EFI_IMAGE_SCN_MEM_WRITE );
490
 			  EFI_IMAGE_SCN_MEM_WRITE );
396
 		applicable_start = &data_start;
491
 		applicable_start = &data_start;
397
 		applicable_end = &data_mid;
492
 		applicable_end = &data_mid;
398
-	} else if ( flags & SEC_READONLY ) {
493
+	} else if ( shdr->sh_type == SHT_PROGBITS ) {
399
 		/* .rodata-type section */
494
 		/* .rodata-type section */
400
 		new->hdr.Characteristics =
495
 		new->hdr.Characteristics =
401
 			( EFI_IMAGE_SCN_CNT_INITIALIZED_DATA |
496
 			( EFI_IMAGE_SCN_CNT_INITIALIZED_DATA |
403
 			  EFI_IMAGE_SCN_MEM_READ );
498
 			  EFI_IMAGE_SCN_MEM_READ );
404
 		applicable_start = &data_start;
499
 		applicable_start = &data_start;
405
 		applicable_end = &data_mid;
500
 		applicable_end = &data_mid;
406
-	} else if ( ! ( flags & SEC_LOAD ) ) {
501
+	} else if ( shdr->sh_type == SHT_NOBITS ) {
407
 		/* .bss-type section */
502
 		/* .bss-type section */
408
 		new->hdr.Characteristics =
503
 		new->hdr.Characteristics =
409
 			( EFI_IMAGE_SCN_CNT_UNINITIALIZED_DATA |
504
 			( EFI_IMAGE_SCN_CNT_UNINITIALIZED_DATA |
413
 		applicable_start = &data_mid;
508
 		applicable_start = &data_mid;
414
 		applicable_end = &data_end;
509
 		applicable_end = &data_end;
415
 	} else {
510
 	} else {
416
-		eprintf ( "Unrecognised characteristics %#lx for section %s\n",
417
-			  flags, section->name );
511
+		eprintf ( "Unrecognised characteristics for section %s\n",
512
+			  name );
418
 		exit ( 1 );
513
 		exit ( 1 );
419
 	}
514
 	}
420
 
515
 
421
 	/* Copy in section contents */
516
 	/* Copy in section contents */
422
-	if ( flags & SEC_LOAD ) {
423
-		if ( ! bfd_get_section_contents ( bfd, section, new->contents,
424
-						  0, section_memsz ) ) {
425
-			eprintf ( "Cannot read section %s: ", section->name );
426
-			bfd_perror ( NULL );
427
-			exit ( 1 );
428
-		}
517
+	if ( shdr->sh_type == SHT_PROGBITS ) {
518
+		memcpy ( new->contents, ( elf->data + shdr->sh_offset ),
519
+			 shdr->sh_size );
429
 	}
520
 	}
430
 
521
 
431
 	/* Update RVA limits */
522
 	/* Update RVA limits */
445
 	/* Write RVA limits back to file header */
536
 	/* Write RVA limits back to file header */
446
 	pe_header->nt.OptionalHeader.BaseOfCode = code_start;
537
 	pe_header->nt.OptionalHeader.BaseOfCode = code_start;
447
 	pe_header->nt.OptionalHeader.SizeOfCode = ( code_end - code_start );
538
 	pe_header->nt.OptionalHeader.SizeOfCode = ( code_end - code_start );
448
-#if defined(EFI_TARGET_IA32)
539
+#if defined(EFI_TARGET32)
449
 	pe_header->nt.OptionalHeader.BaseOfData = data_start;
540
 	pe_header->nt.OptionalHeader.BaseOfData = data_start;
450
 #endif
541
 #endif
451
 	pe_header->nt.OptionalHeader.SizeOfInitializedData =
542
 	pe_header->nt.OptionalHeader.SizeOfInitializedData =
465
 /**
556
 /**
466
  * Process relocation record
557
  * Process relocation record
467
  *
558
  *
468
- * @v bfd		BFD file
469
- * @v section		Section
470
- * @v rel		Relocation entry
559
+ * @v elf		ELF file
560
+ * @v shdr		ELF section header
561
+ * @v syms		Symbol table
562
+ * @v nsyms		Number of symbol table entries
563
+ * @v rel		Relocation record
471
  * @v pe_reltab		PE relocation table to fill in
564
  * @v pe_reltab		PE relocation table to fill in
472
  */
565
  */
473
-static void process_reloc ( bfd *bfd __attribute__ (( unused )),
474
-			    asection *section, arelent *rel,
475
-			    struct pe_relocs **pe_reltab ) {
476
-	reloc_howto_type *howto = rel->howto;
477
-	asymbol *sym = *(rel->sym_ptr_ptr);
478
-	unsigned long offset = ( bfd_get_section_vma ( bfd, section ) +
479
-				 rel->address );
480
-
481
-	if ( bfd_is_abs_section ( sym->section ) ) {
566
+static void process_reloc ( struct elf_file *elf, const Elf_Shdr *shdr,
567
+			    const Elf_Sym *syms, unsigned int nsyms,
568
+			    const Elf_Rel *rel, struct pe_relocs **pe_reltab ) {
569
+	unsigned int type = ELF_R_TYPE ( rel->r_info );
570
+	unsigned int sym = ELF_R_SYM ( rel->r_info );
571
+	size_t offset = ( shdr->sh_addr + rel->r_offset );
572
+
573
+	/* Look up symbol and process relocation */
574
+	if ( sym >= nsyms ) {
575
+		eprintf ( "Symbol out of range\n" );
576
+		exit ( 1 );
577
+	}
578
+	if ( syms[sym].st_shndx == SHN_ABS ) {
482
 		/* Skip absolute symbols; the symbol value won't
579
 		/* Skip absolute symbols; the symbol value won't
483
 		 * change when the object is loaded.
580
 		 * change when the object is loaded.
484
 		 */
581
 		 */
485
-	} else if ( ( strcmp ( howto->name, "R_386_NONE" ) == 0 ) ||
486
-		    ( strcmp ( howto->name, "R_X86_64_NONE" ) == 0 ) ) {
582
+	} else if ( type == elf->machine->r_none ) {
487
 		/* Ignore dummy relocations used by REQUIRE_SYMBOL() */
583
 		/* Ignore dummy relocations used by REQUIRE_SYMBOL() */
488
-	} else if ( strcmp ( howto->name, "R_X86_64_64" ) == 0 ) {
489
-		/* Generate an 8-byte PE relocation */
490
-		generate_pe_reloc ( pe_reltab, offset, 8 );
491
-	} else if ( strcmp ( howto->name, "R_386_32" ) == 0 ) {
492
-		/* Generate a 4-byte PE relocation */
493
-		generate_pe_reloc ( pe_reltab, offset, 4 );
494
-	} else if ( strcmp ( howto->name, "R_386_16" ) == 0 ) {
495
-		/* Generate a 2-byte PE relocation */
496
-		generate_pe_reloc ( pe_reltab, offset, 2 );
497
-	} else if ( ( strcmp ( howto->name, "R_386_PC32" ) == 0 ) ||
498
-		    ( strcmp ( howto->name, "R_X86_64_PC32" ) == 0 ) ) {
584
+	} else if ( type == elf->machine->r_abs ) {
585
+		/* Generate an 8-byte or 4-byte PE relocation */
586
+		generate_pe_reloc ( pe_reltab, offset, sizeof ( Elf_Addr ) );
587
+	} else if ( type == elf->machine->r_pcrel ) {
499
 		/* Skip PC-relative relocations; all relative offsets
588
 		/* Skip PC-relative relocations; all relative offsets
500
 		 * remain unaltered when the object is loaded.
589
 		 * remain unaltered when the object is loaded.
501
 		 */
590
 		 */
502
 	} else {
591
 	} else {
503
-		eprintf ( "Unrecognised relocation type %s\n", howto->name );
592
+		eprintf ( "Unrecognised relocation type %d\n", type );
504
 		exit ( 1 );
593
 		exit ( 1 );
505
 	}
594
 	}
506
 }
595
 }
507
 
596
 
597
+/**
598
+ * Process relocation records
599
+ *
600
+ * @v elf		ELF file
601
+ * @v shdr		ELF section header
602
+ * @v stride		Relocation record size
603
+ * @v pe_reltab		PE relocation table to fill in
604
+ */
605
+static void process_relocs ( struct elf_file *elf, const Elf_Shdr *shdr,
606
+			     size_t stride, struct pe_relocs **pe_reltab ) {
607
+	const Elf_Shdr *symtab;
608
+	const Elf_Sym *syms;
609
+	const Elf_Rel *rel;
610
+	unsigned int nsyms;
611
+	unsigned int nrels;
612
+	unsigned int i;
613
+
614
+	/* Identify symbol table */
615
+	symtab = ( elf->data + elf->ehdr->e_shoff +
616
+		   ( shdr->sh_link * elf->ehdr->e_shentsize ) );
617
+	syms = ( elf->data + symtab->sh_offset );
618
+	nsyms = ( symtab->sh_size / sizeof ( syms[0] ) );
619
+
620
+	/* Process each relocation */
621
+	rel = ( elf->data + shdr->sh_offset );
622
+	nrels = ( shdr->sh_size / stride );
623
+	for ( i = 0 ; i < nrels ; i++ ) {
624
+		process_reloc ( elf, shdr, syms, nsyms, rel, pe_reltab );
625
+		rel = ( ( ( const void * ) rel ) + stride );
626
+	}
627
+}
628
+
508
 /**
629
 /**
509
  * Create relocations section
630
  * Create relocations section
510
  *
631
  *
696
 static void elf2pe ( const char *elf_name, const char *pe_name,
817
 static void elf2pe ( const char *elf_name, const char *pe_name,
697
 		     struct options *opts ) {
818
 		     struct options *opts ) {
698
 	char pe_name_tmp[ strlen ( pe_name ) + 1 ];
819
 	char pe_name_tmp[ strlen ( pe_name ) + 1 ];
699
-	bfd *bfd;
700
-	asymbol **symtab;
701
-	asection *section;
702
-	arelent **reltab;
703
-	arelent **rel;
704
 	struct pe_relocs *pe_reltab = NULL;
820
 	struct pe_relocs *pe_reltab = NULL;
705
 	struct pe_section *pe_sections = NULL;
821
 	struct pe_section *pe_sections = NULL;
706
 	struct pe_section **next_pe_section = &pe_sections;
822
 	struct pe_section **next_pe_section = &pe_sections;
707
 	struct pe_header pe_header;
823
 	struct pe_header pe_header;
824
+	struct elf_file elf;
825
+	const Elf_Shdr *shdr;
826
+	size_t offset;
827
+	unsigned int i;
708
 	FILE *pe;
828
 	FILE *pe;
709
 
829
 
710
 	/* Create a modifiable copy of the PE name */
830
 	/* Create a modifiable copy of the PE name */
711
 	memcpy ( pe_name_tmp, pe_name, sizeof ( pe_name_tmp ) );
831
 	memcpy ( pe_name_tmp, pe_name, sizeof ( pe_name_tmp ) );
712
 
832
 
713
-	/* Open the file */
714
-	bfd = open_input_bfd ( elf_name );
715
-	symtab = read_symtab ( bfd );
833
+	/* Read ELF file */
834
+	read_elf_file ( elf_name, &elf );
716
 
835
 
717
 	/* Initialise the PE header */
836
 	/* Initialise the PE header */
718
 	memcpy ( &pe_header, &efi_pe_header, sizeof ( pe_header ) );
837
 	memcpy ( &pe_header, &efi_pe_header, sizeof ( pe_header ) );
719
-	pe_header.nt.OptionalHeader.AddressOfEntryPoint =
720
-		bfd_get_start_address ( bfd );
838
+	pe_header.nt.FileHeader.Machine = elf.machine->pe_machine;
839
+	pe_header.nt.OptionalHeader.AddressOfEntryPoint = elf.ehdr->e_entry;
721
 	pe_header.nt.OptionalHeader.Subsystem = opts->subsystem;
840
 	pe_header.nt.OptionalHeader.Subsystem = opts->subsystem;
722
 
841
 
723
-	/* For each input section, build an output section and create
724
-	 * the appropriate relocation records
725
-	 */
726
-	for ( section = bfd->sections ; section ; section = section->next ) {
727
-		/* Discard non-allocatable sections */
728
-		if ( ! ( bfd_get_section_flags ( bfd, section ) & SEC_ALLOC ) )
729
-			continue;
730
-		/* Create output section */
731
-		*(next_pe_section) = process_section ( bfd, &pe_header,
732
-						       section );
733
-		next_pe_section = &(*next_pe_section)->next;
734
-		/* Add relocations from this section */
735
-		reltab = read_reltab ( bfd, symtab, section );
736
-		for ( rel = reltab ; *rel ; rel++ )
737
-			process_reloc ( bfd, section, *rel, &pe_reltab );
738
-		free ( reltab );
842
+	/* Process input sections */
843
+	for ( i = 0 ; i < elf.ehdr->e_shnum ; i++ ) {
844
+		offset = ( elf.ehdr->e_shoff + ( i * elf.ehdr->e_shentsize ) );
845
+		shdr = ( elf.data + offset );
846
+
847
+		/* Process section */
848
+		if ( shdr->sh_flags & SHF_ALLOC ) {
849
+
850
+			/* Create output section */
851
+			*(next_pe_section) = process_section ( &elf, shdr,
852
+							       &pe_header );
853
+			next_pe_section = &(*next_pe_section)->next;
854
+
855
+		} else if ( shdr->sh_type == SHT_REL ) {
856
+
857
+			/* Process .rel relocations */
858
+			process_relocs ( &elf, shdr, sizeof ( Elf_Rel ),
859
+					 &pe_reltab );
860
+
861
+		} else if ( shdr->sh_type == SHT_RELA ) {
862
+
863
+			/* Process .rela relocations */
864
+			process_relocs ( &elf, shdr, sizeof ( Elf_Rela ),
865
+					 &pe_reltab );
866
+		}
739
 	}
867
 	}
740
 
868
 
741
 	/* Create the .reloc section */
869
 	/* Create the .reloc section */
742
 	*(next_pe_section) = create_reloc_section ( &pe_header, pe_reltab );
870
 	*(next_pe_section) = create_reloc_section ( &pe_header, pe_reltab );
743
 	next_pe_section = &(*next_pe_section)->next;
871
 	next_pe_section = &(*next_pe_section)->next;
744
 
872
 
745
-	/* Create the .reloc section */
873
+	/* Create the .debug section */
746
 	*(next_pe_section) = create_debug_section ( &pe_header,
874
 	*(next_pe_section) = create_debug_section ( &pe_header,
747
 						    basename ( pe_name_tmp ) );
875
 						    basename ( pe_name_tmp ) );
748
 	next_pe_section = &(*next_pe_section)->next;
876
 	next_pe_section = &(*next_pe_section)->next;
757
 	write_pe_file ( &pe_header, pe_sections, pe );
885
 	write_pe_file ( &pe_header, pe_sections, pe );
758
 	fclose ( pe );
886
 	fclose ( pe );
759
 
887
 
760
-	/* Close BFD file */
761
-	bfd_close ( bfd );
888
+	/* Unmap ELF file */
889
+	munmap ( elf.data, elf.len );
762
 }
890
 }
763
 
891
 
764
 /**
892
 /**
825
 	const char *infile;
953
 	const char *infile;
826
 	const char *outfile;
954
 	const char *outfile;
827
 
955
 
828
-	/* Initialise libbfd */
829
-	bfd_init();
830
-
831
 	/* Parse command-line arguments */
956
 	/* Parse command-line arguments */
832
 	infile_index = parse_options ( argc, argv, &opts );
957
 	infile_index = parse_options ( argc, argv, &opts );
833
 	if ( argc != ( infile_index + 2 ) ) {
958
 	if ( argc != ( infile_index + 2 ) ) {

Loading…
Cancel
Save