mirror of
https://github.com/acidanthera/audk.git
synced 2025-07-29 08:34:07 +02:00
automagically convert ELF to PE/COFF (i386 only)
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@2181 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
parent
0dce6dc1b7
commit
8ba7afaf2e
@ -21,6 +21,15 @@ Abstract:
|
|||||||
|
|
||||||
#include "WinNtInclude.h"
|
#include "WinNtInclude.h"
|
||||||
|
|
||||||
|
//
|
||||||
|
// List of OS and CPU which support ELF to PE conversion
|
||||||
|
//
|
||||||
|
#if defined(linux)
|
||||||
|
#if defined(i386)
|
||||||
|
#define HAVE_ELF
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef __GNUC__
|
#ifndef __GNUC__
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#endif
|
#endif
|
||||||
@ -28,6 +37,10 @@ Abstract:
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
|
||||||
|
#ifdef HAVE_ELF
|
||||||
|
#include <elf.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <Common/UefiBaseTypes.h>
|
#include <Common/UefiBaseTypes.h>
|
||||||
#include <Common/EfiImage.h>
|
#include <Common/EfiImage.h>
|
||||||
@ -49,6 +62,8 @@ typedef unsigned char *PUCHAR;
|
|||||||
typedef unsigned short USHORT;
|
typedef unsigned short USHORT;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
PUCHAR InImageName;
|
||||||
|
|
||||||
static
|
static
|
||||||
void
|
void
|
||||||
Version (
|
Version (
|
||||||
@ -69,7 +84,7 @@ Usage (
|
|||||||
printf ("\nUsage: " UTILITY_NAME " {-t time-date} {-h|--help|-?|/?|-V|--version} \n\
|
printf ("\nUsage: " UTILITY_NAME " {-t time-date} {-h|--help|-?|/?|-V|--version} \n\
|
||||||
[BASE|SEC|PEI_CORE|PEIM|DXE_CORE|DXE_DRIVER|DXE_RUNTIME_DRIVER|\n\
|
[BASE|SEC|PEI_CORE|PEIM|DXE_CORE|DXE_DRIVER|DXE_RUNTIME_DRIVER|\n\
|
||||||
DXE_SAL_DRIVER|DXE_SMM_DRIVER|TOOL|UEFI_DRIVER|UEFI_APPLICATION|\n\
|
DXE_SAL_DRIVER|DXE_SMM_DRIVER|TOOL|UEFI_DRIVER|UEFI_APPLICATION|\n\
|
||||||
USER_DEFINED] peimage [outimage]");
|
USER_DEFINED] peimage [outimage]\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
@ -144,6 +159,548 @@ FWriteFile (
|
|||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_ELF
|
||||||
|
INTN
|
||||||
|
IsElfHeader(
|
||||||
|
UINT8 *FileBuffer
|
||||||
|
)
|
||||||
|
{
|
||||||
|
return (FileBuffer[EI_MAG0] == ELFMAG0
|
||||||
|
&& FileBuffer[EI_MAG1] == ELFMAG1
|
||||||
|
&& FileBuffer[EI_MAG2] == ELFMAG2
|
||||||
|
&& FileBuffer[EI_MAG3] == ELFMAG3);
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef Elf32_Shdr Elf_Shdr;
|
||||||
|
typedef Elf32_Ehdr Elf_Ehdr;
|
||||||
|
typedef Elf32_Rel Elf_Rel;
|
||||||
|
typedef Elf32_Sym Elf_Sym;
|
||||||
|
#define ELFCLASS ELFCLASS32
|
||||||
|
#define ELF_R_TYPE(r) ELF32_R_TYPE(r)
|
||||||
|
#define ELF_R_SYM(r) ELF32_R_SYM(r)
|
||||||
|
|
||||||
|
//
|
||||||
|
// Well known ELF structures.
|
||||||
|
//
|
||||||
|
Elf_Ehdr *Ehdr;
|
||||||
|
Elf_Shdr *ShdrBase;
|
||||||
|
|
||||||
|
//
|
||||||
|
// PE section alignment.
|
||||||
|
//
|
||||||
|
const UINT32 CoffAlignment = 0x20;
|
||||||
|
const UINT32 CoffNbrSections = 4;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Current offset in coff file.
|
||||||
|
//
|
||||||
|
UINT32 CoffOffset;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Result Coff file in memory.
|
||||||
|
//
|
||||||
|
UINT8 *CoffFile;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Offset in Coff file of headers and sections.
|
||||||
|
//
|
||||||
|
UINT32 NtHdrOffset;
|
||||||
|
UINT32 TableOffset;
|
||||||
|
UINT32 TextOffset;
|
||||||
|
UINT32 DataOffset;
|
||||||
|
UINT32 RelocOffset;
|
||||||
|
|
||||||
|
//
|
||||||
|
// ELF sections to offset in Coff file.
|
||||||
|
//
|
||||||
|
UINT32 *CoffSectionsOffset;
|
||||||
|
|
||||||
|
EFI_IMAGE_BASE_RELOCATION *CoffBaseRel;
|
||||||
|
UINT16 *CoffEntryRel;
|
||||||
|
|
||||||
|
UINT32
|
||||||
|
CoffAlign(
|
||||||
|
UINT32 Offset
|
||||||
|
)
|
||||||
|
{
|
||||||
|
return (Offset + CoffAlignment - 1) & ~(CoffAlignment - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
Elf_Shdr *
|
||||||
|
GetShdrByIndex(
|
||||||
|
UINT32 Num
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (Num >= Ehdr->e_shnum)
|
||||||
|
return NULL;
|
||||||
|
return (Elf_Shdr*)((UINT8*)ShdrBase + Num * Ehdr->e_shentsize);
|
||||||
|
}
|
||||||
|
|
||||||
|
INTN
|
||||||
|
CheckElfHeader(
|
||||||
|
VOID
|
||||||
|
)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// Note: Magic has already been tested.
|
||||||
|
//
|
||||||
|
if (Ehdr->e_ident[EI_CLASS] != ELFCLASS)
|
||||||
|
return 0;
|
||||||
|
if (Ehdr->e_ident[EI_DATA] != ELFDATA2LSB)
|
||||||
|
return 0;
|
||||||
|
if (Ehdr->e_type != ET_EXEC)
|
||||||
|
return 0;
|
||||||
|
if (Ehdr->e_machine != EM_386)
|
||||||
|
return 0;
|
||||||
|
if (Ehdr->e_version != EV_CURRENT)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
ShdrBase = (Elf_Shdr *)((UINT8 *)Ehdr + Ehdr->e_shoff);
|
||||||
|
|
||||||
|
CoffSectionsOffset = (UINT32 *)malloc(Ehdr->e_shnum * sizeof (UINT32));
|
||||||
|
memset(CoffSectionsOffset, 0, Ehdr->e_shnum * sizeof(UINT32));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
IsTextShdr(
|
||||||
|
Elf_Shdr *Shdr
|
||||||
|
)
|
||||||
|
{
|
||||||
|
return (Shdr->sh_flags & (SHF_WRITE | SHF_ALLOC)) == SHF_ALLOC;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
IsDataShdr(
|
||||||
|
Elf_Shdr *Shdr
|
||||||
|
)
|
||||||
|
{
|
||||||
|
return (Shdr->sh_flags & (SHF_WRITE | SHF_ALLOC)) == (SHF_ALLOC | SHF_WRITE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CreateSectionHeader(
|
||||||
|
const char *Name,
|
||||||
|
UINT32 Offset,
|
||||||
|
UINT32 Size,
|
||||||
|
UINT32 Flags
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_IMAGE_SECTION_HEADER *Hdr;
|
||||||
|
Hdr = (EFI_IMAGE_SECTION_HEADER*)(CoffFile + TableOffset);
|
||||||
|
|
||||||
|
strcpy(Hdr->Name, Name);
|
||||||
|
Hdr->Misc.VirtualSize = Size;
|
||||||
|
Hdr->VirtualAddress = Offset;
|
||||||
|
Hdr->SizeOfRawData = Size;
|
||||||
|
Hdr->PointerToRawData = Offset;
|
||||||
|
Hdr->PointerToRelocations = 0;
|
||||||
|
Hdr->PointerToLinenumbers = 0;
|
||||||
|
Hdr->NumberOfRelocations = 0;
|
||||||
|
Hdr->NumberOfLinenumbers = 0;
|
||||||
|
Hdr->Characteristics = Flags;
|
||||||
|
|
||||||
|
TableOffset += sizeof (EFI_IMAGE_SECTION_HEADER);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ScanSections(
|
||||||
|
VOID
|
||||||
|
)
|
||||||
|
{
|
||||||
|
UINT32 i;
|
||||||
|
EFI_IMAGE_DOS_HEADER *DosHdr;
|
||||||
|
EFI_IMAGE_NT_HEADERS *NtHdr;
|
||||||
|
UINT32 CoffEntry = 0;
|
||||||
|
|
||||||
|
CoffOffset = 0;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Coff file start with a DOS header.
|
||||||
|
//
|
||||||
|
CoffOffset = sizeof(EFI_IMAGE_DOS_HEADER) + 0x40;
|
||||||
|
NtHdrOffset = CoffOffset;
|
||||||
|
CoffOffset += sizeof(EFI_IMAGE_NT_HEADERS);
|
||||||
|
TableOffset = CoffOffset;
|
||||||
|
CoffOffset += CoffNbrSections * sizeof(EFI_IMAGE_SECTION_HEADER);
|
||||||
|
|
||||||
|
//
|
||||||
|
// First text sections.
|
||||||
|
//
|
||||||
|
CoffOffset = CoffAlign(CoffOffset);
|
||||||
|
TextOffset = CoffOffset;
|
||||||
|
for (i = 0; i < Ehdr->e_shnum; i++) {
|
||||||
|
Elf_Shdr *shdr = GetShdrByIndex(i);
|
||||||
|
if (IsTextShdr(shdr)) {
|
||||||
|
/* Relocate entry. */
|
||||||
|
if (Ehdr->e_entry >= shdr->sh_addr
|
||||||
|
&& Ehdr->e_entry < shdr->sh_addr + shdr->sh_size) {
|
||||||
|
CoffEntry = CoffOffset + Ehdr->e_entry - shdr->sh_addr;
|
||||||
|
}
|
||||||
|
CoffSectionsOffset[i] = CoffOffset;
|
||||||
|
CoffOffset += shdr->sh_size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CoffOffset = CoffAlign(CoffOffset);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Then data sections.
|
||||||
|
//
|
||||||
|
DataOffset = CoffOffset;
|
||||||
|
for (i = 0; i < Ehdr->e_shnum; i++) {
|
||||||
|
Elf_Shdr *shdr = GetShdrByIndex(i);
|
||||||
|
if (IsDataShdr(shdr)) {
|
||||||
|
CoffSectionsOffset[i] = CoffOffset;
|
||||||
|
CoffOffset += shdr->sh_size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CoffOffset = CoffAlign(CoffOffset);
|
||||||
|
|
||||||
|
RelocOffset = CoffOffset;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Allocate base Coff file. Will be expanded later for relocations.
|
||||||
|
//
|
||||||
|
CoffFile = (UINT8 *)malloc(CoffOffset);
|
||||||
|
memset(CoffFile, 0, CoffOffset);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Fill headers.
|
||||||
|
//
|
||||||
|
DosHdr = (EFI_IMAGE_DOS_HEADER *)CoffFile;
|
||||||
|
DosHdr->e_magic = EFI_IMAGE_DOS_SIGNATURE;
|
||||||
|
DosHdr->e_lfanew = NtHdrOffset;
|
||||||
|
|
||||||
|
NtHdr = (EFI_IMAGE_NT_HEADERS*)(CoffFile + NtHdrOffset);
|
||||||
|
|
||||||
|
NtHdr->Signature = EFI_IMAGE_NT_SIGNATURE;
|
||||||
|
|
||||||
|
NtHdr->FileHeader.Machine = EFI_IMAGE_MACHINE_IA32;
|
||||||
|
NtHdr->FileHeader.NumberOfSections = CoffNbrSections;
|
||||||
|
NtHdr->FileHeader.TimeDateStamp = time(NULL);
|
||||||
|
NtHdr->FileHeader.PointerToSymbolTable = 0;
|
||||||
|
NtHdr->FileHeader.NumberOfSymbols = 0;
|
||||||
|
NtHdr->FileHeader.SizeOfOptionalHeader = sizeof(NtHdr->OptionalHeader);
|
||||||
|
NtHdr->FileHeader.Characteristics = EFI_IMAGE_FILE_EXECUTABLE_IMAGE
|
||||||
|
| EFI_IMAGE_FILE_LINE_NUMS_STRIPPED
|
||||||
|
| EFI_IMAGE_FILE_LOCAL_SYMS_STRIPPED
|
||||||
|
| EFI_IMAGE_FILE_32BIT_MACHINE;
|
||||||
|
|
||||||
|
NtHdr->OptionalHeader.Magic = EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC;
|
||||||
|
NtHdr->OptionalHeader.SizeOfCode = DataOffset - TextOffset;
|
||||||
|
NtHdr->OptionalHeader.SizeOfInitializedData = RelocOffset - DataOffset;
|
||||||
|
NtHdr->OptionalHeader.SizeOfUninitializedData = 0;
|
||||||
|
NtHdr->OptionalHeader.AddressOfEntryPoint = CoffEntry;
|
||||||
|
NtHdr->OptionalHeader.BaseOfCode = TextOffset;
|
||||||
|
|
||||||
|
NtHdr->OptionalHeader.BaseOfData = DataOffset;
|
||||||
|
NtHdr->OptionalHeader.ImageBase = 0;
|
||||||
|
NtHdr->OptionalHeader.SectionAlignment = CoffAlignment;
|
||||||
|
NtHdr->OptionalHeader.FileAlignment = CoffAlignment;
|
||||||
|
NtHdr->OptionalHeader.SizeOfImage = 0;
|
||||||
|
|
||||||
|
NtHdr->OptionalHeader.SizeOfHeaders = TextOffset;
|
||||||
|
NtHdr->OptionalHeader.NumberOfRvaAndSizes = EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Section headers.
|
||||||
|
//
|
||||||
|
CreateSectionHeader (".text", TextOffset, DataOffset - TextOffset,
|
||||||
|
EFI_IMAGE_SCN_CNT_CODE
|
||||||
|
| EFI_IMAGE_SCN_MEM_EXECUTE
|
||||||
|
| EFI_IMAGE_SCN_MEM_READ);
|
||||||
|
CreateSectionHeader (".data", DataOffset, RelocOffset - DataOffset,
|
||||||
|
EFI_IMAGE_SCN_CNT_INITIALIZED_DATA
|
||||||
|
| EFI_IMAGE_SCN_MEM_WRITE
|
||||||
|
| EFI_IMAGE_SCN_MEM_READ);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
WriteSections(
|
||||||
|
int (*Filter)(Elf_Shdr *)
|
||||||
|
)
|
||||||
|
{
|
||||||
|
UINT32 Idx;
|
||||||
|
|
||||||
|
//
|
||||||
|
// First: copy sections.
|
||||||
|
//
|
||||||
|
for (Idx = 0; Idx < Ehdr->e_shnum; Idx++) {
|
||||||
|
Elf_Shdr *Shdr = GetShdrByIndex(Idx);
|
||||||
|
if ((*Filter)(Shdr)) {
|
||||||
|
switch (Shdr->sh_type) {
|
||||||
|
case SHT_PROGBITS:
|
||||||
|
/* Copy. */
|
||||||
|
memcpy(CoffFile + CoffSectionsOffset[Idx],
|
||||||
|
(UINT8*)Ehdr + Shdr->sh_offset,
|
||||||
|
Shdr->sh_size);
|
||||||
|
break;
|
||||||
|
case SHT_NOBITS:
|
||||||
|
memset(CoffFile + CoffSectionsOffset[Idx], 0, Shdr->sh_size);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Error (NULL, 0, 0, InImageName, "unhandle section type %x",
|
||||||
|
(UINTN)Shdr->sh_type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Second: apply relocations.
|
||||||
|
//
|
||||||
|
for (Idx = 0; Idx < Ehdr->e_shnum; Idx++) {
|
||||||
|
Elf_Shdr *RelShdr = GetShdrByIndex(Idx);
|
||||||
|
if (RelShdr->sh_type != SHT_REL)
|
||||||
|
continue;
|
||||||
|
Elf_Shdr *SecShdr = GetShdrByIndex(RelShdr->sh_info);
|
||||||
|
UINT32 SecOffset = CoffSectionsOffset[RelShdr->sh_info];
|
||||||
|
if (RelShdr->sh_type == SHT_REL && (*Filter)(SecShdr)) {
|
||||||
|
UINT32 RelIdx;
|
||||||
|
Elf_Shdr *SymtabShdr = GetShdrByIndex(RelShdr->sh_link);
|
||||||
|
UINT8 *Symtab = (UINT8*)Ehdr + SymtabShdr->sh_offset;
|
||||||
|
|
||||||
|
for (RelIdx = 0; RelIdx < RelShdr->sh_size; RelIdx += RelShdr->sh_entsize) {
|
||||||
|
Elf_Rel *Rel = (Elf_Rel *)((UINT8*)Ehdr + RelShdr->sh_offset + RelIdx);
|
||||||
|
Elf_Sym *Sym = (Elf_Sym *)
|
||||||
|
(Symtab + ELF_R_SYM(Rel->r_info) * SymtabShdr->sh_entsize);
|
||||||
|
Elf_Shdr *SymShdr;
|
||||||
|
UINT8 *Targ;
|
||||||
|
|
||||||
|
if (Sym->st_shndx == SHN_UNDEF
|
||||||
|
|| Sym->st_shndx == SHN_ABS
|
||||||
|
|| Sym->st_shndx > Ehdr->e_shnum) {
|
||||||
|
Error (NULL, 0, 0, InImageName, "bad symbol definition");
|
||||||
|
}
|
||||||
|
SymShdr = GetShdrByIndex(Sym->st_shndx);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Note: r_offset in a memory address.
|
||||||
|
// Convert it to a pointer in the coff file.
|
||||||
|
//
|
||||||
|
Targ = CoffFile + SecOffset + (Rel->r_offset - SecShdr->sh_addr);
|
||||||
|
|
||||||
|
switch (ELF_R_TYPE(Rel->r_info)) {
|
||||||
|
case R_386_NONE:
|
||||||
|
break;
|
||||||
|
case R_386_32:
|
||||||
|
//
|
||||||
|
// Absolute relocation.
|
||||||
|
//
|
||||||
|
*(UINT32 *)Targ = *(UINT32 *)Targ - SymShdr->sh_addr
|
||||||
|
+ CoffSectionsOffset[Sym->st_shndx];
|
||||||
|
break;
|
||||||
|
case R_386_PC32:
|
||||||
|
//
|
||||||
|
// Relative relocation: Symbol - Ip + Addend
|
||||||
|
//
|
||||||
|
*(UINT32 *)Targ = *(UINT32 *)Targ
|
||||||
|
+ (CoffSectionsOffset[Sym->st_shndx] - SymShdr->sh_addr)
|
||||||
|
- (SecOffset - SecShdr->sh_addr);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Error (NULL, 0, 0, InImageName, "unhandled relocation type %x",
|
||||||
|
ELF_R_TYPE(Rel->r_info));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CoffAddFixupEntry(
|
||||||
|
UINT16 Val
|
||||||
|
)
|
||||||
|
{
|
||||||
|
*CoffEntryRel = Val;
|
||||||
|
CoffEntryRel++;
|
||||||
|
CoffBaseRel->SizeOfBlock += 2;
|
||||||
|
CoffOffset += 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CoffAddFixup(
|
||||||
|
UINT32 Offset,
|
||||||
|
UINT8 Type
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (CoffBaseRel == NULL
|
||||||
|
|| CoffBaseRel->VirtualAddress != (Offset & ~0xfff)) {
|
||||||
|
if (CoffBaseRel != NULL) {
|
||||||
|
//
|
||||||
|
// Add a null entry (is it required ?)
|
||||||
|
//
|
||||||
|
CoffAddFixupEntry (0);
|
||||||
|
//
|
||||||
|
// Pad for alignment.
|
||||||
|
//
|
||||||
|
if (CoffOffset % 4 != 0)
|
||||||
|
CoffAddFixupEntry (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
CoffFile = realloc
|
||||||
|
(CoffFile,
|
||||||
|
CoffOffset + sizeof(EFI_IMAGE_BASE_RELOCATION) + 2*0x1000);
|
||||||
|
memset(CoffFile + CoffOffset, 0,
|
||||||
|
sizeof(EFI_IMAGE_BASE_RELOCATION) + 2*0x1000);
|
||||||
|
|
||||||
|
CoffBaseRel = (EFI_IMAGE_BASE_RELOCATION*)(CoffFile + CoffOffset);
|
||||||
|
CoffBaseRel->VirtualAddress = Offset & ~0xfff;
|
||||||
|
CoffBaseRel->SizeOfBlock = sizeof(EFI_IMAGE_BASE_RELOCATION);
|
||||||
|
|
||||||
|
CoffEntryRel = (UINT16 *)(CoffBaseRel + 1);
|
||||||
|
CoffOffset += sizeof(EFI_IMAGE_BASE_RELOCATION);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Fill the entry.
|
||||||
|
//
|
||||||
|
CoffAddFixupEntry((Type << 12) | (Offset & 0xfff));
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
WriteRelocations(
|
||||||
|
VOID
|
||||||
|
)
|
||||||
|
{
|
||||||
|
UINT32 Idx;
|
||||||
|
EFI_IMAGE_NT_HEADERS *NtHdr;
|
||||||
|
EFI_IMAGE_DATA_DIRECTORY *Dir;
|
||||||
|
|
||||||
|
for (Idx = 0; Idx < Ehdr->e_shnum; Idx++) {
|
||||||
|
Elf_Shdr *RelShdr = GetShdrByIndex(Idx);
|
||||||
|
if (RelShdr->sh_type == SHT_REL) {
|
||||||
|
Elf_Shdr *SecShdr = GetShdrByIndex(RelShdr->sh_info);
|
||||||
|
if (IsTextShdr(SecShdr) || IsDataShdr(SecShdr)) {
|
||||||
|
UINT32 RelIdx;
|
||||||
|
for (RelIdx = 0; RelIdx < RelShdr->sh_size; RelIdx += RelShdr->sh_entsize) {
|
||||||
|
Elf_Rel *Rel = (Elf_Rel *)
|
||||||
|
((UINT8*)Ehdr + RelShdr->sh_offset + RelIdx);
|
||||||
|
switch (ELF_R_TYPE(Rel->r_info)) {
|
||||||
|
case R_386_NONE:
|
||||||
|
case R_386_PC32:
|
||||||
|
break;
|
||||||
|
case R_386_32:
|
||||||
|
CoffAddFixup(CoffSectionsOffset[RelShdr->sh_info]
|
||||||
|
+ (Rel->r_offset - SecShdr->sh_addr),
|
||||||
|
EFI_IMAGE_REL_BASED_HIGHLOW);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Error (NULL, 0, 0, InImageName, "unhandled relocation type %x",
|
||||||
|
ELF_R_TYPE(Rel->r_info));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Pad by adding empty entries.
|
||||||
|
//
|
||||||
|
while (CoffOffset & (CoffAlignment - 1)) {
|
||||||
|
CoffAddFixupEntry(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
CreateSectionHeader (".reloc", RelocOffset, CoffOffset - RelocOffset,
|
||||||
|
EFI_IMAGE_SCN_CNT_INITIALIZED_DATA
|
||||||
|
| EFI_IMAGE_SCN_MEM_DISCARDABLE
|
||||||
|
| EFI_IMAGE_SCN_MEM_READ);
|
||||||
|
|
||||||
|
NtHdr = (EFI_IMAGE_NT_HEADERS *)(CoffFile + NtHdrOffset);
|
||||||
|
Dir = &NtHdr->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC];
|
||||||
|
Dir->VirtualAddress = RelocOffset;
|
||||||
|
Dir->Size = CoffOffset - RelocOffset;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
WriteDebug(
|
||||||
|
VOID
|
||||||
|
)
|
||||||
|
{
|
||||||
|
UINT32 Len = strlen(InImageName) + 1;
|
||||||
|
UINT32 DebugOffset = CoffOffset;
|
||||||
|
EFI_IMAGE_NT_HEADERS *NtHdr;
|
||||||
|
EFI_IMAGE_DATA_DIRECTORY *DataDir;
|
||||||
|
EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *Dir;
|
||||||
|
EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY *Nb10;
|
||||||
|
|
||||||
|
CoffOffset += sizeof(EFI_IMAGE_DEBUG_DIRECTORY_ENTRY)
|
||||||
|
+ sizeof(EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY)
|
||||||
|
+ Len;
|
||||||
|
CoffOffset = CoffAlign(CoffOffset);
|
||||||
|
|
||||||
|
CoffFile = realloc
|
||||||
|
(CoffFile, CoffOffset);
|
||||||
|
memset(CoffFile + DebugOffset, 0, CoffOffset - DebugOffset);
|
||||||
|
|
||||||
|
Dir = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY*)(CoffFile + DebugOffset);
|
||||||
|
Dir->Type = EFI_IMAGE_DEBUG_TYPE_CODEVIEW;
|
||||||
|
Dir->SizeOfData = sizeof(EFI_IMAGE_DEBUG_DIRECTORY_ENTRY) + Len;
|
||||||
|
Dir->RVA = DebugOffset + sizeof(EFI_IMAGE_DEBUG_DIRECTORY_ENTRY);
|
||||||
|
Dir->FileOffset = DebugOffset + sizeof(EFI_IMAGE_DEBUG_DIRECTORY_ENTRY);
|
||||||
|
|
||||||
|
Nb10 = (EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY*)(Dir + 1);
|
||||||
|
Nb10->Signature = CODEVIEW_SIGNATURE_NB10;
|
||||||
|
strcpy ((PUCHAR)(Nb10 + 1), InImageName);
|
||||||
|
|
||||||
|
CreateSectionHeader (".debug", DebugOffset, CoffOffset - DebugOffset,
|
||||||
|
EFI_IMAGE_SCN_CNT_INITIALIZED_DATA
|
||||||
|
| EFI_IMAGE_SCN_MEM_DISCARDABLE
|
||||||
|
| EFI_IMAGE_SCN_MEM_READ);
|
||||||
|
|
||||||
|
NtHdr = (EFI_IMAGE_NT_HEADERS *)(CoffFile + NtHdrOffset);
|
||||||
|
DataDir = &NtHdr->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG];
|
||||||
|
DataDir->VirtualAddress = DebugOffset;
|
||||||
|
DataDir->Size = CoffOffset - DebugOffset;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ConvertElf (
|
||||||
|
UINT8 **FileBuffer,
|
||||||
|
UINTN *FileLength
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_IMAGE_NT_HEADERS *NtHdr;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Check header, read section table.
|
||||||
|
//
|
||||||
|
Ehdr = (Elf32_Ehdr*)*FileBuffer;
|
||||||
|
if (!CheckElfHeader())
|
||||||
|
return;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Compute sections new address.
|
||||||
|
//
|
||||||
|
ScanSections();
|
||||||
|
|
||||||
|
//
|
||||||
|
// Write and relocate sections.
|
||||||
|
//
|
||||||
|
WriteSections(IsTextShdr);
|
||||||
|
WriteSections(IsDataShdr);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Translate and write relocations.
|
||||||
|
//
|
||||||
|
WriteRelocations();
|
||||||
|
|
||||||
|
//
|
||||||
|
// Write debug info.
|
||||||
|
//
|
||||||
|
WriteDebug();
|
||||||
|
|
||||||
|
NtHdr = (EFI_IMAGE_NT_HEADERS *)(CoffFile + NtHdrOffset);
|
||||||
|
NtHdr->OptionalHeader.SizeOfImage = CoffOffset;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Replace.
|
||||||
|
//
|
||||||
|
free(*FileBuffer);
|
||||||
|
*FileBuffer = CoffFile;
|
||||||
|
*FileLength = CoffOffset;
|
||||||
|
}
|
||||||
|
#endif // HAVE_ELF
|
||||||
|
|
||||||
int
|
int
|
||||||
main (
|
main (
|
||||||
int argc,
|
int argc,
|
||||||
@ -273,6 +830,8 @@ Returns:
|
|||||||
return STATUS_ERROR;
|
return STATUS_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
InImageName = argv[2];
|
||||||
|
|
||||||
if (argc == 4) {
|
if (argc == 4) {
|
||||||
OutImageName = argv[3];
|
OutImageName = argv[3];
|
||||||
}
|
}
|
||||||
@ -323,27 +882,32 @@ Returns:
|
|||||||
//
|
//
|
||||||
// open source file
|
// open source file
|
||||||
//
|
//
|
||||||
fpIn = fopen (argv[2], "rb");
|
fpIn = fopen (InImageName, "rb");
|
||||||
if (!fpIn) {
|
if (!fpIn) {
|
||||||
Error (NULL, 0, 0, argv[2], "failed to open input file for reading");
|
Error (NULL, 0, 0, InImageName, "failed to open input file for reading");
|
||||||
return STATUS_ERROR;
|
return STATUS_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
FReadFile (fpIn, (VOID **)&FileBuffer, &FileLength);
|
FReadFile (fpIn, (VOID **)&FileBuffer, &FileLength);
|
||||||
|
|
||||||
|
#ifdef HAVE_ELF
|
||||||
|
if (IsElfHeader(FileBuffer)) {
|
||||||
|
ConvertElf(&FileBuffer, &FileLength);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
//
|
//
|
||||||
// Read the dos & pe hdrs of the image
|
// Read the dos & pe hdrs of the image
|
||||||
//
|
//
|
||||||
DosHdr = (EFI_IMAGE_DOS_HEADER *)FileBuffer;
|
DosHdr = (EFI_IMAGE_DOS_HEADER *)FileBuffer;
|
||||||
if (DosHdr->e_magic != EFI_IMAGE_DOS_SIGNATURE) {
|
if (DosHdr->e_magic != EFI_IMAGE_DOS_SIGNATURE) {
|
||||||
Error (NULL, 0, 0, argv[2], "DOS header signature not found in source image");
|
Error (NULL, 0, 0, InImageName, "DOS header signature not found in source image");
|
||||||
fclose (fpIn);
|
fclose (fpIn);
|
||||||
return STATUS_ERROR;
|
return STATUS_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
PeHdr = (EFI_IMAGE_NT_HEADERS *)(FileBuffer + DosHdr->e_lfanew);
|
PeHdr = (EFI_IMAGE_NT_HEADERS *)(FileBuffer + DosHdr->e_lfanew);
|
||||||
if (PeHdr->Signature != EFI_IMAGE_NT_SIGNATURE) {
|
if (PeHdr->Signature != EFI_IMAGE_NT_SIGNATURE) {
|
||||||
Error (NULL, 0, 0, argv[2], "PE header signature not found in source image");
|
Error (NULL, 0, 0, InImageName, "PE header signature not found in source image");
|
||||||
fclose (fpIn);
|
fclose (fpIn);
|
||||||
return STATUS_ERROR;
|
return STATUS_ERROR;
|
||||||
}
|
}
|
||||||
@ -351,7 +915,7 @@ Returns:
|
|||||||
//
|
//
|
||||||
// open output file
|
// open output file
|
||||||
//
|
//
|
||||||
strcpy (outname, argv[2]);
|
strcpy (outname, InImageName);
|
||||||
pe = NULL;
|
pe = NULL;
|
||||||
for (p = outname; *p; p++) {
|
for (p = outname; *p; p++) {
|
||||||
if (*p == '.') {
|
if (*p == '.') {
|
||||||
@ -389,7 +953,7 @@ Returns:
|
|||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Path the PE header
|
// Patch the PE header
|
||||||
//
|
//
|
||||||
PeHdr->OptionalHeader.Subsystem = (USHORT) Type;
|
PeHdr->OptionalHeader.Subsystem = (USHORT) Type;
|
||||||
if (TimeStampPresent) {
|
if (TimeStampPresent) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user