mirror of
https://github.com/acidanthera/audk.git
synced 2025-09-24 10:17:45 +02:00
ImageTool: Relocate using the IR
This commit is contained in:
parent
3a4c288fd3
commit
75662ff41a
@ -717,7 +717,7 @@ CreateIntermediate (
|
|||||||
|
|
||||||
memcpy (Segments[SIndex].Name, Name, strlen (Name));
|
memcpy (Segments[SIndex].Name, Name, strlen (Name));
|
||||||
|
|
||||||
Segments[SIndex].ImageAddress = Shdr->sh_addr - BaseAddress;
|
Segments[SIndex].ImageAddress = (uint32_t)(Shdr->sh_addr - BaseAddress);
|
||||||
Segments[SIndex].DataSize = (uint32_t)Shdr->sh_size;
|
Segments[SIndex].DataSize = (uint32_t)Shdr->sh_size;
|
||||||
Segments[SIndex].ImageSize = ALIGN_VALUE (Segments[SIndex].DataSize, Context->Alignment);
|
Segments[SIndex].ImageSize = ALIGN_VALUE (Segments[SIndex].DataSize, Context->Alignment);
|
||||||
Segments[SIndex].Read = true;
|
Segments[SIndex].Read = true;
|
||||||
|
@ -41,7 +41,7 @@ CheckToolImageSegment (
|
|||||||
}
|
}
|
||||||
|
|
||||||
Overflow = BaseOverflowAddU32 (
|
Overflow = BaseOverflowAddU32 (
|
||||||
(uint32_t)Segment->ImageAddress,
|
Segment->ImageAddress,
|
||||||
Segment->ImageSize,
|
Segment->ImageSize,
|
||||||
PreviousEndAddress
|
PreviousEndAddress
|
||||||
);
|
);
|
||||||
@ -81,7 +81,7 @@ CheckToolImageSegmentInfo (
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
*ImageSize = (uint32_t)SegmentInfo->Segments[0].ImageAddress;
|
*ImageSize = SegmentInfo->Segments[0].ImageAddress;
|
||||||
for (Index = 0; Index < SegmentInfo->NumSegments; ++Index) {
|
for (Index = 0; Index < SegmentInfo->NumSegments; ++Index) {
|
||||||
Result = CheckToolImageSegment (
|
Result = CheckToolImageSegment (
|
||||||
SegmentInfo,
|
SegmentInfo,
|
||||||
@ -100,17 +100,21 @@ CheckToolImageSegmentInfo (
|
|||||||
static
|
static
|
||||||
const image_tool_segment_t *
|
const image_tool_segment_t *
|
||||||
ImageGetSegmentByAddress (
|
ImageGetSegmentByAddress (
|
||||||
const image_tool_segment_info_t *SegmentInfo,
|
uint32_t *Address,
|
||||||
uint64_t Address
|
uint32_t *RemainingSize,
|
||||||
|
const image_tool_segment_info_t *SegmentInfo
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
uint64_t Index;
|
uint32_t Index;
|
||||||
|
|
||||||
|
assert (Address != NULL);
|
||||||
assert (SegmentInfo != NULL);
|
assert (SegmentInfo != NULL);
|
||||||
|
|
||||||
for (Index = 0; Index < SegmentInfo->NumSegments; ++Index) {
|
for (Index = 0; Index < SegmentInfo->NumSegments; ++Index) {
|
||||||
if ((SegmentInfo->Segments[Index].ImageAddress <= Address)
|
if ((SegmentInfo->Segments[Index].ImageAddress <= *Address)
|
||||||
&& (Address < SegmentInfo->Segments[Index].ImageAddress + SegmentInfo->Segments[Index].ImageSize)) {
|
&& (*Address < SegmentInfo->Segments[Index].ImageAddress + SegmentInfo->Segments[Index].ImageSize)) {
|
||||||
|
*Address -= SegmentInfo->Segments[Index].ImageAddress;
|
||||||
|
*RemainingSize = SegmentInfo->Segments[Index].ImageSize - *Address;
|
||||||
return &SegmentInfo->Segments[Index];
|
return &SegmentInfo->Segments[Index];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -122,20 +126,81 @@ static
|
|||||||
bool
|
bool
|
||||||
CheckToolImageReloc (
|
CheckToolImageReloc (
|
||||||
const image_tool_image_info_t *Image,
|
const image_tool_image_info_t *Image,
|
||||||
|
uint32_t ImageSize,
|
||||||
const image_tool_reloc_t *Reloc
|
const image_tool_reloc_t *Reloc
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
uint32_t RelocOffset;
|
||||||
|
uint32_t RemainingSize;
|
||||||
const image_tool_segment_t *Segment;
|
const image_tool_segment_t *Segment;
|
||||||
|
uint16_t MovHigh;
|
||||||
|
uint16_t MovLow;
|
||||||
|
|
||||||
assert (Image != NULL);
|
assert (Image != NULL);
|
||||||
assert (Reloc != NULL);
|
assert (Reloc != NULL);
|
||||||
|
|
||||||
Segment = ImageGetSegmentByAddress (&Image->SegmentInfo, Reloc->Target);
|
RelocOffset = Reloc->Target;
|
||||||
|
Segment = ImageGetSegmentByAddress (
|
||||||
|
&RelocOffset,
|
||||||
|
&RemainingSize,
|
||||||
|
&Image->SegmentInfo
|
||||||
|
);
|
||||||
if (Segment == NULL) {
|
if (Segment == NULL) {
|
||||||
raise ();
|
raise ();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
switch (Reloc->Type) {
|
||||||
|
case EFI_IMAGE_REL_BASED_HIGHLOW:
|
||||||
|
{
|
||||||
|
if (RemainingSize < sizeof (UINT32)) {
|
||||||
|
raise ();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case EFI_IMAGE_REL_BASED_DIR64:
|
||||||
|
{
|
||||||
|
if (RemainingSize < sizeof (UINT64)) {
|
||||||
|
raise ();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case EFI_IMAGE_REL_BASED_ARM_MOV32T:
|
||||||
|
{
|
||||||
|
if (RemainingSize < sizeof (UINT32)) {
|
||||||
|
raise ();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!IS_ALIGNED (Reloc->Target, ALIGNOF (UINT16))) {
|
||||||
|
raise ();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
MovHigh = *(const uint16_t *)&Segment->Data[RelocOffset];
|
||||||
|
MovLow = *(const uint16_t *)&Segment->Data[RelocOffset + 2];
|
||||||
|
if (((MovHigh & 0xFBF0U) != 0xF200U && (MovHigh & 0xFBF0U) != 0xF2C0U) ||
|
||||||
|
(MovLow & 0x8000U) != 0) {
|
||||||
|
raise ();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
raise ();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*if (Segment->Write) {
|
/*if (Segment->Write) {
|
||||||
printf("!!! writable reloc at %x !!!\n", Reloc->Target);
|
printf("!!! writable reloc at %x !!!\n", Reloc->Target);
|
||||||
}*/
|
}*/
|
||||||
@ -146,7 +211,8 @@ CheckToolImageReloc (
|
|||||||
static
|
static
|
||||||
bool
|
bool
|
||||||
CheckToolImageRelocInfo (
|
CheckToolImageRelocInfo (
|
||||||
const image_tool_image_info_t *Image
|
const image_tool_image_info_t *Image,
|
||||||
|
uint32_t ImageSize
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
const image_tool_reloc_info_t *RelocInfo;
|
const image_tool_reloc_info_t *RelocInfo;
|
||||||
@ -168,7 +234,7 @@ CheckToolImageRelocInfo (
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (Index = 0; Index < RelocInfo->NumRelocs; ++Index) {
|
for (Index = 0; Index < RelocInfo->NumRelocs; ++Index) {
|
||||||
Result = CheckToolImageReloc (Image, &RelocInfo->Relocs[Index]);
|
Result = CheckToolImageReloc (Image, ImageSize, &RelocInfo->Relocs[Index]);
|
||||||
if (!Result) {
|
if (!Result) {
|
||||||
raise ();
|
raise ();
|
||||||
return false;
|
return false;
|
||||||
@ -213,7 +279,7 @@ CheckToolImage (
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Result = CheckToolImageRelocInfo (Image);
|
Result = CheckToolImageRelocInfo (Image, ImageSize);
|
||||||
if (!Result) {
|
if (!Result) {
|
||||||
raise ();
|
raise ();
|
||||||
return false;
|
return false;
|
||||||
@ -307,3 +373,81 @@ ToolImageDestruct (
|
|||||||
|
|
||||||
memset (Image, 0, sizeof (*Image));
|
memset (Image, 0, sizeof (*Image));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
ToolImageRelocate (
|
||||||
|
image_tool_image_info_t *Image,
|
||||||
|
uint64_t BaseAddress
|
||||||
|
)
|
||||||
|
{
|
||||||
|
uint64_t Adjust;
|
||||||
|
const image_tool_reloc_t *Reloc;
|
||||||
|
uint32_t RelocOffset;
|
||||||
|
uint32_t RemainingSize;
|
||||||
|
const image_tool_segment_t *Segment;
|
||||||
|
uint32_t Index;
|
||||||
|
uint32_t RelocTarget32;
|
||||||
|
uint64_t RelocTarget64;
|
||||||
|
|
||||||
|
Adjust = BaseAddress - Image->HeaderInfo.BaseAddress;
|
||||||
|
|
||||||
|
if (Adjust == 0) {
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Index = 0; Index < Image->RelocInfo.NumRelocs; ++Index) {
|
||||||
|
Reloc = &Image->RelocInfo.Relocs[Index];
|
||||||
|
|
||||||
|
RelocOffset = Reloc->Target;
|
||||||
|
Segment = ImageGetSegmentByAddress (
|
||||||
|
&RelocOffset,
|
||||||
|
&RemainingSize,
|
||||||
|
&Image->SegmentInfo
|
||||||
|
);
|
||||||
|
if (Segment == NULL) {
|
||||||
|
raise ();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (Reloc->Type) {
|
||||||
|
case EFI_IMAGE_REL_BASED_HIGHLOW:
|
||||||
|
{
|
||||||
|
assert (RemainingSize >= sizeof (UINT32));
|
||||||
|
|
||||||
|
RelocTarget32 = ReadUnaligned32 ((CONST VOID *)&Segment->Data[RelocOffset]);
|
||||||
|
RelocTarget32 += (uint32_t)Adjust;
|
||||||
|
WriteUnaligned32 ((VOID *)&Segment->Data[RelocOffset], RelocTarget32);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case EFI_IMAGE_REL_BASED_DIR64:
|
||||||
|
{
|
||||||
|
assert (RemainingSize >= sizeof (UINT64));
|
||||||
|
|
||||||
|
RelocTarget64 = ReadUnaligned64 ((CONST VOID *)&Segment->Data[RelocOffset]);
|
||||||
|
RelocTarget64 += Adjust;
|
||||||
|
WriteUnaligned64 ((VOID *)&Segment->Data[RelocOffset], RelocTarget64);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case EFI_IMAGE_REL_BASED_ARM_MOV32T:
|
||||||
|
{
|
||||||
|
assert (RemainingSize >= sizeof (UINT32));
|
||||||
|
assert (IS_ALIGNED (Reloc->Target, ALIGNOF (UINT16)));
|
||||||
|
|
||||||
|
PeCoffThumbMovwMovtImmediateFixup (&Segment->Data[RelocOffset], Adjust);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
raise ();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Image->HeaderInfo.BaseAddress = BaseAddress;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
@ -50,71 +50,6 @@ HiiBin (
|
|||||||
return RETURN_SUCCESS;
|
return RETURN_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
|
||||||
RETURN_STATUS
|
|
||||||
Rebase (
|
|
||||||
IN const char *BaseAddress,
|
|
||||||
IN const char *OldName,
|
|
||||||
IN const char *NewName
|
|
||||||
)
|
|
||||||
{
|
|
||||||
RETURN_STATUS Status;
|
|
||||||
void *Pe;
|
|
||||||
uint32_t PeSize;
|
|
||||||
UINT64 NewBaseAddress;
|
|
||||||
PE_COFF_LOADER_IMAGE_CONTEXT Context;
|
|
||||||
EFI_IMAGE_NT_HEADERS32 *PeHdr32;
|
|
||||||
EFI_IMAGE_NT_HEADERS64 *PeHdr64;
|
|
||||||
|
|
||||||
assert (BaseAddress != NULL);
|
|
||||||
assert (OldName != NULL);
|
|
||||||
assert (NewName != NULL);
|
|
||||||
|
|
||||||
Status = AsciiStrHexToUint64S (BaseAddress, NULL, &NewBaseAddress);
|
|
||||||
if (RETURN_ERROR (Status)) {
|
|
||||||
fprintf (stderr, "ImageTool: Could not convert ASCII string to UINT64\n");
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
|
|
||||||
Pe = UserReadFile (OldName, &PeSize);
|
|
||||||
if (Pe == NULL) {
|
|
||||||
fprintf (stderr, "ImageTool: Could not open %s: %s\n", OldName, strerror (errno));
|
|
||||||
return RETURN_ABORTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
Status = PeCoffInitializeContext (&Context, Pe, (UINT32)PeSize);
|
|
||||||
if (RETURN_ERROR (Status)) {
|
|
||||||
fprintf (stderr, "ImageTool: Could not initialise Context\n");
|
|
||||||
free (Pe);
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
|
|
||||||
Context.ImageBuffer = (void *)Context.FileBuffer;
|
|
||||||
|
|
||||||
Status = PeCoffRelocateImage (&Context, NewBaseAddress, NULL, 0);
|
|
||||||
if (EFI_ERROR (Status)) {
|
|
||||||
fprintf (stderr, "ImageTool: Could not relocate image\n");
|
|
||||||
free (Pe);
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Context.ImageType == PeCoffLoaderTypePe32) {
|
|
||||||
PeHdr32 = (EFI_IMAGE_NT_HEADERS32 *)(void *)((char *)Context.ImageBuffer + Context.ExeHdrOffset);
|
|
||||||
PeHdr32->ImageBase = (UINT32)NewBaseAddress;
|
|
||||||
} else if (Context.ImageType == PeCoffLoaderTypePe32Plus) {
|
|
||||||
PeHdr64 = (EFI_IMAGE_NT_HEADERS64 *)(void *)((char *)Context.ImageBuffer + Context.ExeHdrOffset);
|
|
||||||
PeHdr64->ImageBase = NewBaseAddress;
|
|
||||||
} else {
|
|
||||||
assert (false);
|
|
||||||
}
|
|
||||||
|
|
||||||
UserWriteFile (NewName, Pe, PeSize);
|
|
||||||
|
|
||||||
free (Pe);
|
|
||||||
|
|
||||||
return RETURN_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
static
|
static
|
||||||
RETURN_STATUS
|
RETURN_STATUS
|
||||||
CheckAcpiTable (
|
CheckAcpiTable (
|
||||||
@ -342,7 +277,8 @@ GenExecutable (
|
|||||||
IN const char *OutputFileName,
|
IN const char *OutputFileName,
|
||||||
IN const char *InputFileName,
|
IN const char *InputFileName,
|
||||||
IN const char *FormatName,
|
IN const char *FormatName,
|
||||||
IN const char *TypeName
|
IN const char *TypeName,
|
||||||
|
IN const char *BaseAddress
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
UINT32 InputFileSize;
|
UINT32 InputFileSize;
|
||||||
@ -350,6 +286,7 @@ GenExecutable (
|
|||||||
RETURN_STATUS Status;
|
RETURN_STATUS Status;
|
||||||
bool Result;
|
bool Result;
|
||||||
image_tool_image_info_t ImageInfo;
|
image_tool_image_info_t ImageInfo;
|
||||||
|
UINT64 NewBaseAddress;
|
||||||
void *OutputFile;
|
void *OutputFile;
|
||||||
uint32_t OutputFileSize;
|
uint32_t OutputFileSize;
|
||||||
|
|
||||||
@ -385,6 +322,22 @@ GenExecutable (
|
|||||||
return RETURN_UNSUPPORTED;
|
return RETURN_UNSUPPORTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (BaseAddress != NULL) {
|
||||||
|
Status = AsciiStrHexToUint64S (BaseAddress, NULL, &NewBaseAddress);
|
||||||
|
if (RETURN_ERROR (Status)) {
|
||||||
|
fprintf (stderr, "ImageTool: Could not convert ASCII string to UINT64\n");
|
||||||
|
ToolImageDestruct (&ImageInfo);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result = ToolImageRelocate (&ImageInfo, NewBaseAddress);
|
||||||
|
if (!Result) {
|
||||||
|
fprintf (stderr, "ImageTool: Failed to relocate input file %s\n", InputFileName);
|
||||||
|
ToolImageDestruct (&ImageInfo);
|
||||||
|
return RETURN_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (strcmp (FormatName, "PE") == 0) {
|
if (strcmp (FormatName, "PE") == 0) {
|
||||||
OutputFile = ToolImageEmitPe (&ImageInfo, &OutputFileSize);
|
OutputFile = ToolImageEmitPe (&ImageInfo, &OutputFileSize);
|
||||||
} else {
|
} else {
|
||||||
@ -423,7 +376,7 @@ int main (int argc, const char *argv[])
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
Status = GenExecutable (argv[3], argv[2], "PE", argv[4]);
|
Status = GenExecutable (argv[3], argv[2], "PE", argv[4], NULL);
|
||||||
if (RETURN_ERROR (Status)) {
|
if (RETURN_ERROR (Status)) {
|
||||||
raise ();
|
raise ();
|
||||||
return -1;
|
return -1;
|
||||||
@ -466,7 +419,7 @@ int main (int argc, const char *argv[])
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
Status = Rebase (argv[2], argv[3], argv[4]);
|
Status = GenExecutable (argv[4], argv[3], "PE", NULL, argv[2]);
|
||||||
if (RETURN_ERROR (Status)) {
|
if (RETURN_ERROR (Status)) {
|
||||||
raise ();
|
raise ();
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -46,7 +46,7 @@ typedef struct {
|
|||||||
char *Name;
|
char *Name;
|
||||||
uint8_t *Data;
|
uint8_t *Data;
|
||||||
uint32_t DataSize;
|
uint32_t DataSize;
|
||||||
uint64_t ImageAddress;
|
uint32_t ImageAddress;
|
||||||
uint32_t ImageSize;
|
uint32_t ImageSize;
|
||||||
bool Read;
|
bool Read;
|
||||||
bool Write;
|
bool Write;
|
||||||
@ -108,6 +108,12 @@ ImageConvertToXip (
|
|||||||
image_tool_image_info_t *Image
|
image_tool_image_info_t *Image
|
||||||
);
|
);
|
||||||
|
|
||||||
|
bool
|
||||||
|
ToolImageRelocate (
|
||||||
|
image_tool_image_info_t *Image,
|
||||||
|
uint64_t BaseAddress
|
||||||
|
);
|
||||||
|
|
||||||
RETURN_STATUS
|
RETURN_STATUS
|
||||||
ToolContextConstructPe (
|
ToolContextConstructPe (
|
||||||
OUT image_tool_image_info_t *Image,
|
OUT image_tool_image_info_t *Image,
|
||||||
|
@ -563,14 +563,14 @@ ToolImageEmitPeSections (
|
|||||||
|
|
||||||
if (Segment->Execute) {
|
if (Segment->Execute) {
|
||||||
if (FirstCode) {
|
if (FirstCode) {
|
||||||
Context->PeHdr->BaseOfCode = (UINT32)Segment->ImageAddress;
|
Context->PeHdr->BaseOfCode = Segment->ImageAddress;
|
||||||
FirstCode = false;
|
FirstCode = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#if PE_ARCH == 32
|
#if PE_ARCH == 32
|
||||||
else {
|
else {
|
||||||
if (FirstData) {
|
if (FirstData) {
|
||||||
Context->PeHdr->BaseOfData = (UINT32)Segment->ImageAddress;
|
Context->PeHdr->BaseOfData = Segment->ImageAddress;
|
||||||
FirstData = false;
|
FirstData = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -596,11 +596,11 @@ ToolImageEmitPeSections (
|
|||||||
SectionsSize += SectionPadding;
|
SectionsSize += SectionPadding;
|
||||||
|
|
||||||
if (Segment->Execute) {
|
if (Segment->Execute) {
|
||||||
Context->PeHdr->BaseOfCode = MIN(Context->PeHdr->BaseOfCode, (UINT32)Segment->ImageAddress);
|
Context->PeHdr->BaseOfCode = MIN(Context->PeHdr->BaseOfCode, Segment->ImageAddress);
|
||||||
Context->PeHdr->SizeOfCode += Segment->ImageSize;
|
Context->PeHdr->SizeOfCode += Segment->ImageSize;
|
||||||
} else {
|
} else {
|
||||||
#if PE_ARCH == 32
|
#if PE_ARCH == 32
|
||||||
Context->PeHdr->BaseOfData = MIN(Context->PeHdr->BaseOfData, (UINT32)Segment->ImageAddress);
|
Context->PeHdr->BaseOfData = MIN(Context->PeHdr->BaseOfData, Segment->ImageAddress);
|
||||||
#endif
|
#endif
|
||||||
Context->PeHdr->SizeOfInitializedData += Segment->ImageSize;
|
Context->PeHdr->SizeOfInitializedData += Segment->ImageSize;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user