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,8 +53,6 @@ EINFO		:= ./util/einfo
53 53
 GENKEYMAP	:= ./util/genkeymap.pl
54 54
 DOXYGEN		:= doxygen
55 55
 LCAB		:= lcab
56
-BINUTILS_DIR	:= /usr
57
-BFD_DIR		:= $(BINUTILS_DIR)
58 56
 ZLIB_DIR	:= /usr
59 57
 
60 58
 ###############################################################################

+ 4
- 6
src/Makefile.housekeeping View File

@@ -1303,20 +1303,18 @@ CLEANUP += $(ZBIN)
1303 1303
 #
1304 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 1309
 $(ELF2EFI32) : util/elf2efi.c $(MAKEDEPS)
1312 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 1312
 		$(ELF2EFI_LDFLAGS) -o $@
1315 1313
 CLEANUP += $(ELF2EFI32)
1316 1314
 
1317 1315
 $(ELF2EFI64) : util/elf2efi.c $(MAKEDEPS)
1318 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 1318
 		$(ELF2EFI_LDFLAGS) -o $@
1321 1319
 CLEANUP += $(ELF2EFI64)
1322 1320
 

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

@@ -17,9 +17,6 @@
17 17
  * 02110-1301, USA.
18 18
  */
19 19
 
20
-#define _GNU_SOURCE
21
-#define PACKAGE "elf2efi"
22
-#define PACKAGE_VERSION "1"
23 20
 #define FILE_LICENCE(...) extern void __file_licence ( void )
24 21
 #include <stdint.h>
25 22
 #include <stddef.h>
@@ -30,15 +27,65 @@
30 27
 #include <errno.h>
31 28
 #include <assert.h>
32 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 35
 #include <ipxe/efi/Uefi.h>
35 36
 #include <ipxe/efi/IndustryStandard/PeImage.h>
36 37
 #include <libgen.h>
37 38
 
38 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 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 89
 struct pe_section {
43 90
 	struct pe_section *next;
44 91
 	EFI_IMAGE_SECTION_HEADER hdr;
@@ -57,11 +104,7 @@ struct pe_relocs {
57 104
 struct pe_header {
58 105
 	EFI_IMAGE_DOS_HEADER dos;
59 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 110
 static struct pe_header efi_pe_header = {
@@ -72,26 +115,15 @@ static struct pe_header efi_pe_header = {
72 115
 	.nt = {
73 116
 		.Signature = EFI_IMAGE_NT_SIGNATURE,
74 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 118
 			.TimeDateStamp = 0x10d1a884,
81 119
 			.SizeOfOptionalHeader =
82 120
 				sizeof ( efi_pe_header.nt.OptionalHeader ),
83 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 123
 					     EFI_IMAGE_FILE_EXECUTABLE_IMAGE ),
88 124
 		},
89 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 127
 			.MajorLinkerVersion = 42,
96 128
 			.MinorLinkerVersion = 42,
97 129
 			.SectionAlignment = EFI_FILE_ALIGN,
@@ -104,6 +136,20 @@ static struct pe_header efi_pe_header = {
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 153
 /** Command-line options */
108 154
 struct options {
109 155
 	unsigned int subsystem;
@@ -235,110 +281,155 @@ static size_t output_pe_reltab ( struct pe_relocs *pe_reltab,
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 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 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 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 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 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 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 419
  * Process section
329 420
  *
330
- * @v bfd		BFD file
421
+ * @v elf		ELF file
422
+ * @v shdr		ELF section header
331 423
  * @v pe_header		PE file header
332
- * @v section		Section
333 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 429
 	struct pe_section *new;
430
+	const char *name;
339 431
 	size_t section_memsz;
340 432
 	size_t section_filesz;
341
-	unsigned long flags = bfd_get_section_flags ( bfd, section );
342 433
 	unsigned long code_start;
343 434
 	unsigned long code_end;
344 435
 	unsigned long data_start;
@@ -349,12 +440,15 @@ static struct pe_section * process_section ( bfd *bfd,
349 440
 	unsigned long *applicable_start;
350 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 446
 	/* Extract current RVA limits from file header */
353 447
 	code_start = pe_header->nt.OptionalHeader.BaseOfCode;
354 448
 	code_end = ( code_start + pe_header->nt.OptionalHeader.SizeOfCode );
355
-#if defined(EFI_TARGET_IA32)
449
+#if defined(EFI_TARGET32)
356 450
 	data_start = pe_header->nt.OptionalHeader.BaseOfData;
357
-#elif defined(EFI_TARGET_X64)
451
+#elif defined(EFI_TARGET64)
358 452
 	data_start = code_end;
359 453
 #endif
360 454
 	data_mid = ( data_start +
@@ -363,21 +457,21 @@ static struct pe_section * process_section ( bfd *bfd,
363 457
 		     pe_header->nt.OptionalHeader.SizeOfUninitializedData );
364 458
 
365 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 462
 			   efi_file_align ( section_memsz ) : 0 );
369 463
 	new = xmalloc ( sizeof ( *new ) + section_filesz );
370 464
 	memset ( new, 0, sizeof ( *new ) + section_filesz );
371 465
 
372 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 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 470
 	new->hdr.SizeOfRawData = section_filesz;
378 471
 
379 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 475
 		/* .text-type section */
382 476
 		new->hdr.Characteristics =
383 477
 			( EFI_IMAGE_SCN_CNT_CODE |
@@ -386,7 +480,8 @@ static struct pe_section * process_section ( bfd *bfd,
386 480
 			  EFI_IMAGE_SCN_MEM_READ );
387 481
 		applicable_start = &code_start;
388 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 485
 		/* .data-type section */
391 486
 		new->hdr.Characteristics =
392 487
 			( EFI_IMAGE_SCN_CNT_INITIALIZED_DATA |
@@ -395,7 +490,7 @@ static struct pe_section * process_section ( bfd *bfd,
395 490
 			  EFI_IMAGE_SCN_MEM_WRITE );
396 491
 		applicable_start = &data_start;
397 492
 		applicable_end = &data_mid;
398
-	} else if ( flags & SEC_READONLY ) {
493
+	} else if ( shdr->sh_type == SHT_PROGBITS ) {
399 494
 		/* .rodata-type section */
400 495
 		new->hdr.Characteristics =
401 496
 			( EFI_IMAGE_SCN_CNT_INITIALIZED_DATA |
@@ -403,7 +498,7 @@ static struct pe_section * process_section ( bfd *bfd,
403 498
 			  EFI_IMAGE_SCN_MEM_READ );
404 499
 		applicable_start = &data_start;
405 500
 		applicable_end = &data_mid;
406
-	} else if ( ! ( flags & SEC_LOAD ) ) {
501
+	} else if ( shdr->sh_type == SHT_NOBITS ) {
407 502
 		/* .bss-type section */
408 503
 		new->hdr.Characteristics =
409 504
 			( EFI_IMAGE_SCN_CNT_UNINITIALIZED_DATA |
@@ -413,19 +508,15 @@ static struct pe_section * process_section ( bfd *bfd,
413 508
 		applicable_start = &data_mid;
414 509
 		applicable_end = &data_end;
415 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 513
 		exit ( 1 );
419 514
 	}
420 515
 
421 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 522
 	/* Update RVA limits */
@@ -445,7 +536,7 @@ static struct pe_section * process_section ( bfd *bfd,
445 536
 	/* Write RVA limits back to file header */
446 537
 	pe_header->nt.OptionalHeader.BaseOfCode = code_start;
447 538
 	pe_header->nt.OptionalHeader.SizeOfCode = ( code_end - code_start );
448
-#if defined(EFI_TARGET_IA32)
539
+#if defined(EFI_TARGET32)
449 540
 	pe_header->nt.OptionalHeader.BaseOfData = data_start;
450 541
 #endif
451 542
 	pe_header->nt.OptionalHeader.SizeOfInitializedData =
@@ -465,46 +556,76 @@ static struct pe_section * process_section ( bfd *bfd,
465 556
 /**
466 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 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 579
 		/* Skip absolute symbols; the symbol value won't
483 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 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 588
 		/* Skip PC-relative relocations; all relative offsets
500 589
 		 * remain unaltered when the object is loaded.
501 590
 		 */
502 591
 	} else {
503
-		eprintf ( "Unrecognised relocation type %s\n", howto->name );
592
+		eprintf ( "Unrecognised relocation type %d\n", type );
504 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 630
  * Create relocations section
510 631
  *
@@ -696,53 +817,60 @@ static void write_pe_file ( struct pe_header *pe_header,
696 817
 static void elf2pe ( const char *elf_name, const char *pe_name,
697 818
 		     struct options *opts ) {
698 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 820
 	struct pe_relocs *pe_reltab = NULL;
705 821
 	struct pe_section *pe_sections = NULL;
706 822
 	struct pe_section **next_pe_section = &pe_sections;
707 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 828
 	FILE *pe;
709 829
 
710 830
 	/* Create a modifiable copy of the PE name */
711 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 836
 	/* Initialise the PE header */
718 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 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 869
 	/* Create the .reloc section */
742 870
 	*(next_pe_section) = create_reloc_section ( &pe_header, pe_reltab );
743 871
 	next_pe_section = &(*next_pe_section)->next;
744 872
 
745
-	/* Create the .reloc section */
873
+	/* Create the .debug section */
746 874
 	*(next_pe_section) = create_debug_section ( &pe_header,
747 875
 						    basename ( pe_name_tmp ) );
748 876
 	next_pe_section = &(*next_pe_section)->next;
@@ -757,8 +885,8 @@ static void elf2pe ( const char *elf_name, const char *pe_name,
757 885
 	write_pe_file ( &pe_header, pe_sections, pe );
758 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,9 +953,6 @@ int main ( int argc, char **argv ) {
825 953
 	const char *infile;
826 954
 	const char *outfile;
827 955
 
828
-	/* Initialise libbfd */
829
-	bfd_init();
830
-
831 956
 	/* Parse command-line arguments */
832 957
 	infile_index = parse_options ( argc, argv, &opts );
833 958
 	if ( argc != ( infile_index + 2 ) ) {

Loading…
Cancel
Save