mirror of
https://github.com/acidanthera/audk.git
synced 2025-09-24 02:07:44 +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));
|
||||
|
||||
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].ImageSize = ALIGN_VALUE (Segments[SIndex].DataSize, Context->Alignment);
|
||||
Segments[SIndex].Read = true;
|
||||
|
@ -41,7 +41,7 @@ CheckToolImageSegment (
|
||||
}
|
||||
|
||||
Overflow = BaseOverflowAddU32 (
|
||||
(uint32_t)Segment->ImageAddress,
|
||||
Segment->ImageAddress,
|
||||
Segment->ImageSize,
|
||||
PreviousEndAddress
|
||||
);
|
||||
@ -81,7 +81,7 @@ CheckToolImageSegmentInfo (
|
||||
return false;
|
||||
}
|
||||
|
||||
*ImageSize = (uint32_t)SegmentInfo->Segments[0].ImageAddress;
|
||||
*ImageSize = SegmentInfo->Segments[0].ImageAddress;
|
||||
for (Index = 0; Index < SegmentInfo->NumSegments; ++Index) {
|
||||
Result = CheckToolImageSegment (
|
||||
SegmentInfo,
|
||||
@ -100,17 +100,21 @@ CheckToolImageSegmentInfo (
|
||||
static
|
||||
const image_tool_segment_t *
|
||||
ImageGetSegmentByAddress (
|
||||
const image_tool_segment_info_t *SegmentInfo,
|
||||
uint64_t Address
|
||||
uint32_t *Address,
|
||||
uint32_t *RemainingSize,
|
||||
const image_tool_segment_info_t *SegmentInfo
|
||||
)
|
||||
{
|
||||
uint64_t Index;
|
||||
uint32_t Index;
|
||||
|
||||
assert (Address != NULL);
|
||||
assert (SegmentInfo != NULL);
|
||||
|
||||
for (Index = 0; Index < SegmentInfo->NumSegments; ++Index) {
|
||||
if ((SegmentInfo->Segments[Index].ImageAddress <= Address)
|
||||
&& (Address < SegmentInfo->Segments[Index].ImageAddress + SegmentInfo->Segments[Index].ImageSize)) {
|
||||
if ((SegmentInfo->Segments[Index].ImageAddress <= *Address)
|
||||
&& (*Address < SegmentInfo->Segments[Index].ImageAddress + SegmentInfo->Segments[Index].ImageSize)) {
|
||||
*Address -= SegmentInfo->Segments[Index].ImageAddress;
|
||||
*RemainingSize = SegmentInfo->Segments[Index].ImageSize - *Address;
|
||||
return &SegmentInfo->Segments[Index];
|
||||
}
|
||||
}
|
||||
@ -122,20 +126,81 @@ static
|
||||
bool
|
||||
CheckToolImageReloc (
|
||||
const image_tool_image_info_t *Image,
|
||||
uint32_t ImageSize,
|
||||
const image_tool_reloc_t *Reloc
|
||||
)
|
||||
{
|
||||
uint32_t RelocOffset;
|
||||
uint32_t RemainingSize;
|
||||
const image_tool_segment_t *Segment;
|
||||
uint16_t MovHigh;
|
||||
uint16_t MovLow;
|
||||
|
||||
assert (Image != NULL);
|
||||
assert (Reloc != NULL);
|
||||
|
||||
Segment = ImageGetSegmentByAddress (&Image->SegmentInfo, Reloc->Target);
|
||||
RelocOffset = Reloc->Target;
|
||||
Segment = ImageGetSegmentByAddress (
|
||||
&RelocOffset,
|
||||
&RemainingSize,
|
||||
&Image->SegmentInfo
|
||||
);
|
||||
if (Segment == NULL) {
|
||||
raise ();
|
||||
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) {
|
||||
printf("!!! writable reloc at %x !!!\n", Reloc->Target);
|
||||
}*/
|
||||
@ -146,7 +211,8 @@ CheckToolImageReloc (
|
||||
static
|
||||
bool
|
||||
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;
|
||||
@ -168,7 +234,7 @@ CheckToolImageRelocInfo (
|
||||
}
|
||||
|
||||
for (Index = 0; Index < RelocInfo->NumRelocs; ++Index) {
|
||||
Result = CheckToolImageReloc (Image, &RelocInfo->Relocs[Index]);
|
||||
Result = CheckToolImageReloc (Image, ImageSize, &RelocInfo->Relocs[Index]);
|
||||
if (!Result) {
|
||||
raise ();
|
||||
return false;
|
||||
@ -213,7 +279,7 @@ CheckToolImage (
|
||||
return false;
|
||||
}
|
||||
|
||||
Result = CheckToolImageRelocInfo (Image);
|
||||
Result = CheckToolImageRelocInfo (Image, ImageSize);
|
||||
if (!Result) {
|
||||
raise ();
|
||||
return false;
|
||||
@ -307,3 +373,81 @@ ToolImageDestruct (
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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
|
||||
RETURN_STATUS
|
||||
CheckAcpiTable (
|
||||
@ -342,7 +277,8 @@ GenExecutable (
|
||||
IN const char *OutputFileName,
|
||||
IN const char *InputFileName,
|
||||
IN const char *FormatName,
|
||||
IN const char *TypeName
|
||||
IN const char *TypeName,
|
||||
IN const char *BaseAddress
|
||||
)
|
||||
{
|
||||
UINT32 InputFileSize;
|
||||
@ -350,6 +286,7 @@ GenExecutable (
|
||||
RETURN_STATUS Status;
|
||||
bool Result;
|
||||
image_tool_image_info_t ImageInfo;
|
||||
UINT64 NewBaseAddress;
|
||||
void *OutputFile;
|
||||
uint32_t OutputFileSize;
|
||||
|
||||
@ -385,6 +322,22 @@ GenExecutable (
|
||||
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) {
|
||||
OutputFile = ToolImageEmitPe (&ImageInfo, &OutputFileSize);
|
||||
} else {
|
||||
@ -423,7 +376,7 @@ int main (int argc, const char *argv[])
|
||||
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)) {
|
||||
raise ();
|
||||
return -1;
|
||||
@ -466,7 +419,7 @@ int main (int argc, const char *argv[])
|
||||
return -1;
|
||||
}
|
||||
|
||||
Status = Rebase (argv[2], argv[3], argv[4]);
|
||||
Status = GenExecutable (argv[4], argv[3], "PE", NULL, argv[2]);
|
||||
if (RETURN_ERROR (Status)) {
|
||||
raise ();
|
||||
return -1;
|
||||
|
@ -46,7 +46,7 @@ typedef struct {
|
||||
char *Name;
|
||||
uint8_t *Data;
|
||||
uint32_t DataSize;
|
||||
uint64_t ImageAddress;
|
||||
uint32_t ImageAddress;
|
||||
uint32_t ImageSize;
|
||||
bool Read;
|
||||
bool Write;
|
||||
@ -108,6 +108,12 @@ ImageConvertToXip (
|
||||
image_tool_image_info_t *Image
|
||||
);
|
||||
|
||||
bool
|
||||
ToolImageRelocate (
|
||||
image_tool_image_info_t *Image,
|
||||
uint64_t BaseAddress
|
||||
);
|
||||
|
||||
RETURN_STATUS
|
||||
ToolContextConstructPe (
|
||||
OUT image_tool_image_info_t *Image,
|
||||
|
@ -563,14 +563,14 @@ ToolImageEmitPeSections (
|
||||
|
||||
if (Segment->Execute) {
|
||||
if (FirstCode) {
|
||||
Context->PeHdr->BaseOfCode = (UINT32)Segment->ImageAddress;
|
||||
Context->PeHdr->BaseOfCode = Segment->ImageAddress;
|
||||
FirstCode = false;
|
||||
}
|
||||
}
|
||||
#if PE_ARCH == 32
|
||||
else {
|
||||
if (FirstData) {
|
||||
Context->PeHdr->BaseOfData = (UINT32)Segment->ImageAddress;
|
||||
Context->PeHdr->BaseOfData = Segment->ImageAddress;
|
||||
FirstData = false;
|
||||
}
|
||||
}
|
||||
@ -596,11 +596,11 @@ ToolImageEmitPeSections (
|
||||
SectionsSize += SectionPadding;
|
||||
|
||||
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;
|
||||
} else {
|
||||
#if PE_ARCH == 32
|
||||
Context->PeHdr->BaseOfData = MIN(Context->PeHdr->BaseOfData, (UINT32)Segment->ImageAddress);
|
||||
Context->PeHdr->BaseOfData = MIN(Context->PeHdr->BaseOfData, Segment->ImageAddress);
|
||||
#endif
|
||||
Context->PeHdr->SizeOfInitializedData += Segment->ImageSize;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user