|  | @@ -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 ) ) {
 |