2023-06-26 12:23:02 +02:00
|
|
|
/** @file
|
|
|
|
Copyright (c) 2021, Marvin Häuser. All rights reserved.
|
|
|
|
Copyright (c) 2022, Mikhail Krichanov. All rights reserved.
|
|
|
|
SPDX-License-Identifier: BSD-3-Clause
|
|
|
|
**/
|
|
|
|
|
|
|
|
#include "ImageTool.h"
|
|
|
|
|
|
|
|
static
|
|
|
|
bool
|
|
|
|
CheckToolImageSegment (
|
|
|
|
const image_tool_segment_info_t *SegmentInfo,
|
|
|
|
const image_tool_segment_t *Segment,
|
|
|
|
uint32_t *PreviousEndAddress
|
|
|
|
)
|
|
|
|
{
|
|
|
|
bool Overflow;
|
|
|
|
|
2024-07-01 11:18:06 +02:00
|
|
|
// LCOV_EXCL_START
|
2023-06-26 12:23:02 +02:00
|
|
|
if (!IS_ALIGNED (Segment->ImageSize, SegmentInfo->SegmentAlignment)) {
|
2024-07-01 11:18:06 +02:00
|
|
|
assert (false);
|
2023-06-26 12:23:02 +02:00
|
|
|
return false;
|
|
|
|
}
|
2024-07-01 11:18:06 +02:00
|
|
|
// LCOV_EXCL_STOP
|
2023-06-26 12:23:02 +02:00
|
|
|
|
|
|
|
if (Segment->Write && Segment->Execute) {
|
2023-12-15 14:28:15 +01:00
|
|
|
DEBUG_RAISE ();
|
2023-06-26 12:23:02 +02:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (Segment->ImageAddress != *PreviousEndAddress) {
|
2023-12-15 14:28:15 +01:00
|
|
|
DEBUG_RAISE ();
|
2023-06-26 12:23:02 +02:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
Overflow = BaseOverflowAddU32 (
|
2024-07-01 11:18:06 +02:00
|
|
|
Segment->ImageAddress,
|
|
|
|
Segment->ImageSize,
|
|
|
|
PreviousEndAddress
|
|
|
|
);
|
|
|
|
// LCOV_EXCL_START
|
2023-06-26 12:23:02 +02:00
|
|
|
if (Overflow) {
|
2024-07-01 11:18:06 +02:00
|
|
|
assert (false);
|
2023-06-26 12:23:02 +02:00
|
|
|
return false;
|
|
|
|
}
|
2024-07-01 11:18:06 +02:00
|
|
|
// LCOV_EXCL_STOP
|
2023-06-26 12:23:02 +02:00
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
static
|
|
|
|
bool
|
|
|
|
CheckToolImageSegmentInfo (
|
|
|
|
const image_tool_segment_info_t *SegmentInfo,
|
|
|
|
uint32_t *ImageSize
|
|
|
|
)
|
|
|
|
{
|
|
|
|
uint32_t Index;
|
|
|
|
bool Result;
|
|
|
|
|
2024-07-01 11:18:06 +02:00
|
|
|
// LCOV_EXCL_START
|
2023-06-26 12:23:02 +02:00
|
|
|
if (!IS_POW2 (SegmentInfo->SegmentAlignment)) {
|
2024-07-01 11:18:06 +02:00
|
|
|
assert (false);
|
2023-06-26 12:23:02 +02:00
|
|
|
return false;
|
|
|
|
}
|
2024-07-01 11:18:06 +02:00
|
|
|
// LCOV_EXCL_STOP
|
2023-06-26 12:23:02 +02:00
|
|
|
|
|
|
|
if (SegmentInfo->NumSegments == 0) {
|
2023-12-15 14:28:15 +01:00
|
|
|
DEBUG_RAISE ();
|
2023-06-26 12:23:02 +02:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2024-07-01 11:18:06 +02:00
|
|
|
// LCOV_EXCL_START
|
2023-06-26 12:23:02 +02:00
|
|
|
if (!IS_ALIGNED (SegmentInfo->Segments[0].ImageAddress, SegmentInfo->SegmentAlignment)) {
|
2024-07-01 11:18:06 +02:00
|
|
|
assert (false);
|
2023-06-26 12:23:02 +02:00
|
|
|
return false;
|
|
|
|
}
|
2024-07-01 11:18:06 +02:00
|
|
|
// LCOV_EXCL_STOP
|
2023-06-26 12:23:02 +02:00
|
|
|
|
|
|
|
*ImageSize = SegmentInfo->Segments[0].ImageAddress;
|
|
|
|
for (Index = 0; Index < SegmentInfo->NumSegments; ++Index) {
|
|
|
|
Result = CheckToolImageSegment (
|
2024-07-01 11:18:06 +02:00
|
|
|
SegmentInfo,
|
|
|
|
&SegmentInfo->Segments[Index],
|
|
|
|
ImageSize
|
|
|
|
);
|
2023-06-26 12:23:02 +02:00
|
|
|
if (!Result) {
|
2023-12-15 14:28:15 +01:00
|
|
|
DEBUG_RAISE ();
|
2023-06-26 12:23:02 +02:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
static
|
2023-12-15 14:28:15 +01:00
|
|
|
bool
|
|
|
|
CheckToolImageHeaderInfo (
|
|
|
|
const image_tool_header_info_t *HeaderInfo,
|
|
|
|
const image_tool_segment_info_t *SegmentInfo,
|
|
|
|
uint32_t ImageSize
|
|
|
|
)
|
|
|
|
{
|
|
|
|
if (SegmentInfo->Segments[0].ImageAddress > HeaderInfo->EntryPointAddress ||
|
|
|
|
HeaderInfo->EntryPointAddress > ImageSize) {
|
|
|
|
DEBUG_RAISE ();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2024-07-01 11:18:06 +02:00
|
|
|
// LCOV_EXCL_START
|
2023-12-15 14:28:15 +01:00
|
|
|
if (!IS_ALIGNED (HeaderInfo->BaseAddress, SegmentInfo->SegmentAlignment)) {
|
2024-07-01 11:18:06 +02:00
|
|
|
assert (false);
|
2023-12-15 14:28:15 +01:00
|
|
|
return false;
|
|
|
|
}
|
2024-07-01 11:18:06 +02:00
|
|
|
// LCOV_EXCL_STOP
|
2023-12-15 14:28:15 +01:00
|
|
|
|
2024-07-01 11:18:06 +02:00
|
|
|
// LCOV_EXCL_START
|
2023-12-15 14:28:15 +01:00
|
|
|
if (HeaderInfo->BaseAddress + ImageSize < HeaderInfo->BaseAddress) {
|
2024-07-01 11:18:06 +02:00
|
|
|
assert (false);
|
2023-12-15 14:28:15 +01:00
|
|
|
return false;
|
|
|
|
}
|
2024-07-01 11:18:06 +02:00
|
|
|
// LCOV_EXCL_STOP
|
2023-12-15 14:28:15 +01:00
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2023-06-26 12:23:02 +02:00
|
|
|
const image_tool_segment_t *
|
|
|
|
ImageGetSegmentByAddress (
|
|
|
|
uint32_t *Address,
|
|
|
|
uint32_t *RemainingSize,
|
|
|
|
const image_tool_segment_info_t *SegmentInfo
|
|
|
|
)
|
|
|
|
{
|
|
|
|
uint32_t Index;
|
|
|
|
|
|
|
|
for (Index = 0; Index < SegmentInfo->NumSegments; ++Index) {
|
|
|
|
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];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2023-12-15 14:28:15 +01:00
|
|
|
uint8_t
|
|
|
|
ToolImageGetRelocSize (
|
|
|
|
uint8_t Type
|
|
|
|
)
|
|
|
|
{
|
2024-07-01 11:18:06 +02:00
|
|
|
// LCOV_EXCL_START
|
2023-12-15 14:28:15 +01:00
|
|
|
switch (Type) {
|
2024-07-01 11:18:06 +02:00
|
|
|
// LCOV_EXCL_STOP
|
2023-12-15 14:28:15 +01:00
|
|
|
case EFI_IMAGE_REL_BASED_HIGHLOW:
|
|
|
|
{
|
|
|
|
return sizeof (UINT32);
|
|
|
|
}
|
|
|
|
|
|
|
|
case EFI_IMAGE_REL_BASED_DIR64:
|
|
|
|
{
|
|
|
|
return sizeof (UINT64);
|
|
|
|
}
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
case EFI_IMAGE_REL_BASED_ARM_MOV32T:
|
|
|
|
{
|
|
|
|
return sizeof (UINT32);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2024-07-01 11:18:06 +02:00
|
|
|
// LCOV_EXCL_START
|
2023-12-15 14:28:15 +01:00
|
|
|
default:
|
|
|
|
{
|
2024-07-01 11:18:06 +02:00
|
|
|
break;
|
2023-12-15 14:28:15 +01:00
|
|
|
}
|
2024-07-01 11:18:06 +02:00
|
|
|
// LCOV_EXCL_STOP
|
2023-12-15 14:28:15 +01:00
|
|
|
}
|
2024-07-01 11:18:06 +02:00
|
|
|
|
|
|
|
// LCOV_EXCL_START
|
|
|
|
assert (false);
|
|
|
|
return 0;
|
|
|
|
// LCOV_EXCL_STOP
|
2023-12-15 14:28:15 +01:00
|
|
|
}
|
|
|
|
|
2023-06-26 12:23:02 +02:00
|
|
|
static
|
|
|
|
bool
|
|
|
|
CheckToolImageReloc (
|
|
|
|
const image_tool_image_info_t *Image,
|
2023-12-15 14:28:15 +01:00
|
|
|
const image_tool_reloc_t *Reloc,
|
|
|
|
uint8_t RelocSize
|
2023-06-26 12:23:02 +02:00
|
|
|
)
|
|
|
|
{
|
|
|
|
uint32_t RelocOffset;
|
|
|
|
uint32_t RemainingSize;
|
|
|
|
const image_tool_segment_t *Segment;
|
2023-12-15 14:28:15 +01:00
|
|
|
|
|
|
|
#if 0
|
2023-06-26 12:23:02 +02:00
|
|
|
uint16_t MovHigh;
|
|
|
|
uint16_t MovLow;
|
2023-12-15 14:28:15 +01:00
|
|
|
#endif
|
2023-06-26 12:23:02 +02:00
|
|
|
|
|
|
|
RelocOffset = Reloc->Target;
|
|
|
|
Segment = ImageGetSegmentByAddress (
|
|
|
|
&RelocOffset,
|
|
|
|
&RemainingSize,
|
|
|
|
&Image->SegmentInfo
|
|
|
|
);
|
|
|
|
if (Segment == NULL) {
|
2023-12-15 14:28:15 +01:00
|
|
|
DEBUG_RAISE ();
|
2023-06-26 12:23:02 +02:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2023-12-15 14:28:15 +01:00
|
|
|
if (RelocSize > RemainingSize) {
|
|
|
|
DEBUG_RAISE ();
|
|
|
|
return false;
|
|
|
|
}
|
2023-06-26 12:23:02 +02:00
|
|
|
|
2023-12-15 14:28:15 +01:00
|
|
|
#if 0
|
|
|
|
if (Reloc->Type == EFI_IMAGE_REL_BASED_ARM_MOV32T) {
|
|
|
|
if (!IS_ALIGNED (Reloc->Target, ALIGNOF (UINT16))) {
|
|
|
|
DEBUG_RAISE ();
|
|
|
|
return false;
|
2023-06-26 12:23:02 +02:00
|
|
|
}
|
|
|
|
|
2023-12-15 14:28:15 +01:00
|
|
|
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) {
|
|
|
|
DEBUG_RAISE ();
|
2023-06-26 12:23:02 +02:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
2023-12-15 14:28:15 +01:00
|
|
|
#endif
|
2023-06-26 12:23:02 +02:00
|
|
|
|
2023-12-15 14:28:15 +01:00
|
|
|
// FIXME: Update drivers?
|
2024-07-01 11:18:06 +02:00
|
|
|
if (Image->HeaderInfo.Subsystem == EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER &&
|
|
|
|
Segment->Write) {
|
2023-06-26 12:23:02 +02:00
|
|
|
printf("!!! writable reloc at %x !!!\n", Reloc->Target);
|
2023-12-15 14:28:15 +01:00
|
|
|
//DEBUG_RAISE ();
|
|
|
|
//return false;
|
|
|
|
}
|
2023-06-26 12:23:02 +02:00
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
static
|
|
|
|
bool
|
|
|
|
CheckToolImageRelocInfo (
|
2023-12-15 14:28:15 +01:00
|
|
|
const image_tool_image_info_t *Image
|
2023-06-26 12:23:02 +02:00
|
|
|
)
|
|
|
|
{
|
|
|
|
const image_tool_reloc_info_t *RelocInfo;
|
2023-12-15 14:28:15 +01:00
|
|
|
uint8_t RelocSize;
|
|
|
|
uint32_t MinRelocTarget;
|
2023-06-26 12:23:02 +02:00
|
|
|
uint32_t Index;
|
|
|
|
bool Result;
|
|
|
|
|
|
|
|
RelocInfo = &Image->RelocInfo;
|
|
|
|
|
|
|
|
if (RelocInfo->NumRelocs == 0) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2024-07-01 11:18:06 +02:00
|
|
|
// LCOV_EXCL_START
|
2023-12-15 14:28:15 +01:00
|
|
|
if (RelocInfo->RelocsStripped) {
|
2024-07-01 11:18:06 +02:00
|
|
|
assert (false);
|
2023-06-26 12:23:02 +02:00
|
|
|
return false;
|
|
|
|
}
|
2024-07-01 11:18:06 +02:00
|
|
|
// LCOV_EXCL_STOP
|
2023-06-26 12:23:02 +02:00
|
|
|
|
|
|
|
if (RelocInfo->NumRelocs > (MAX_UINT32 / sizeof (UINT16))) {
|
2023-12-15 14:28:15 +01:00
|
|
|
DEBUG_RAISE ();
|
2023-06-26 12:23:02 +02:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2023-12-15 14:28:15 +01:00
|
|
|
MinRelocTarget = 0;
|
|
|
|
|
|
|
|
for (Index = 0; Index < RelocInfo->NumRelocs; ++Index) {
|
|
|
|
if (RelocInfo->Relocs[Index].Target < MinRelocTarget) {
|
|
|
|
DEBUG_RAISE ();
|
|
|
|
return false;
|
|
|
|
}
|
2023-06-26 12:23:02 +02:00
|
|
|
|
2023-12-15 14:28:15 +01:00
|
|
|
RelocSize = ToolImageGetRelocSize (RelocInfo->Relocs[Index].Type);
|
2024-07-01 11:18:06 +02:00
|
|
|
// LCOV_EXCL_START
|
2023-12-15 14:28:15 +01:00
|
|
|
if (RelocSize == 0) {
|
2024-07-01 11:18:06 +02:00
|
|
|
assert (false);
|
2023-06-26 12:23:02 +02:00
|
|
|
return false;
|
|
|
|
}
|
2024-07-01 11:18:06 +02:00
|
|
|
// LCOV_EXCL_STOP
|
2023-06-26 12:23:02 +02:00
|
|
|
|
2023-12-15 14:28:15 +01:00
|
|
|
Result = CheckToolImageReloc (Image, &RelocInfo->Relocs[Index], RelocSize);
|
2023-06-26 12:23:02 +02:00
|
|
|
if (!Result) {
|
2023-12-15 14:28:15 +01:00
|
|
|
DEBUG_RAISE ();
|
2023-06-26 12:23:02 +02:00
|
|
|
return false;
|
|
|
|
}
|
2023-12-15 14:28:15 +01:00
|
|
|
|
|
|
|
MinRelocTarget = RelocInfo->Relocs[Index].Target + RelocSize;
|
2023-06-26 12:23:02 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
static
|
|
|
|
bool
|
|
|
|
CheckToolImageDebugInfo (
|
|
|
|
const image_tool_debug_info_t *DebugInfo
|
|
|
|
)
|
|
|
|
{
|
2023-12-15 14:28:15 +01:00
|
|
|
if (DebugInfo->SymbolsPathLen > MAX_UINT8) {
|
|
|
|
DEBUG_RAISE ();
|
|
|
|
return false;
|
2023-06-26 12:23:02 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
CheckToolImage (
|
|
|
|
const image_tool_image_info_t *Image
|
|
|
|
)
|
|
|
|
{
|
|
|
|
bool Result;
|
|
|
|
uint32_t ImageSize;
|
|
|
|
|
|
|
|
Result = CheckToolImageSegmentInfo (&Image->SegmentInfo, &ImageSize);
|
|
|
|
if (!Result) {
|
2023-12-15 14:28:15 +01:00
|
|
|
DEBUG_RAISE ();
|
2023-06-26 12:23:02 +02:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2023-12-15 14:28:15 +01:00
|
|
|
Result = CheckToolImageHeaderInfo (
|
|
|
|
&Image->HeaderInfo,
|
|
|
|
&Image->SegmentInfo,
|
|
|
|
ImageSize
|
|
|
|
);
|
2023-06-26 12:23:02 +02:00
|
|
|
if (!Result) {
|
2023-12-15 14:28:15 +01:00
|
|
|
DEBUG_RAISE ();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
Result = CheckToolImageRelocInfo (Image);
|
|
|
|
if (!Result) {
|
|
|
|
DEBUG_RAISE ();
|
2023-06-26 12:23:02 +02:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
Result = CheckToolImageDebugInfo (&Image->DebugInfo);
|
|
|
|
if (!Result) {
|
2023-12-15 14:28:15 +01:00
|
|
|
DEBUG_RAISE ();
|
2023-06-26 12:23:02 +02:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
ImageInitUnpaddedSize (
|
|
|
|
const image_tool_image_info_t *Image
|
|
|
|
)
|
|
|
|
{
|
|
|
|
uint32_t Index;
|
|
|
|
image_tool_segment_t *Segment;
|
|
|
|
|
|
|
|
for (Index = 0; Index < Image->SegmentInfo.NumSegments; ++Index) {
|
|
|
|
Segment = &Image->SegmentInfo.Segments[Index];
|
|
|
|
Segment->UnpaddedSize = Segment->ImageSize;
|
|
|
|
|
|
|
|
for (; Segment->UnpaddedSize > 0; --Segment->UnpaddedSize) {
|
|
|
|
if (Segment->Data[Segment->UnpaddedSize - 1] != 0) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
ToolImageDestruct (
|
|
|
|
image_tool_image_info_t *Image
|
|
|
|
)
|
|
|
|
{
|
2024-07-01 11:18:06 +02:00
|
|
|
uint16_t Index;
|
2023-06-26 12:23:02 +02:00
|
|
|
|
2024-07-01 11:18:06 +02:00
|
|
|
// LCOV_EXCL_START
|
2023-06-26 12:23:02 +02:00
|
|
|
if (Image->SegmentInfo.Segments != NULL) {
|
2024-07-01 11:18:06 +02:00
|
|
|
// LCOV_EXCL_STOP
|
2023-06-26 12:23:02 +02:00
|
|
|
for (Index = 0; Index < Image->SegmentInfo.NumSegments; ++Index) {
|
2024-07-01 11:18:06 +02:00
|
|
|
// LCOV_EXCL_START
|
2023-12-15 14:28:15 +01:00
|
|
|
if (Image->SegmentInfo.Segments[Index].Name != NULL) {
|
2024-07-01 11:18:06 +02:00
|
|
|
// LCOV_EXCL_STOP
|
2023-12-15 14:28:15 +01:00
|
|
|
FreePool (Image->SegmentInfo.Segments[Index].Name);
|
|
|
|
}
|
|
|
|
|
2024-07-01 11:18:06 +02:00
|
|
|
// LCOV_EXCL_START
|
2023-12-15 14:28:15 +01:00
|
|
|
if (Image->SegmentInfo.Segments[Index].Data != NULL) {
|
2024-07-01 11:18:06 +02:00
|
|
|
// LCOV_EXCL_STOP
|
2023-12-15 14:28:15 +01:00
|
|
|
FreePool (Image->SegmentInfo.Segments[Index].Data);
|
|
|
|
}
|
2023-06-26 12:23:02 +02:00
|
|
|
}
|
|
|
|
|
2024-07-01 11:18:06 +02:00
|
|
|
// LCOV_EXCL_START
|
2023-12-15 14:28:15 +01:00
|
|
|
if (Image->SegmentInfo.Segments != NULL) {
|
2024-07-01 11:18:06 +02:00
|
|
|
// LCOV_EXCL_STOP
|
2023-12-15 14:28:15 +01:00
|
|
|
FreePool (Image->SegmentInfo.Segments);
|
|
|
|
}
|
2023-06-26 12:23:02 +02:00
|
|
|
}
|
|
|
|
|
2024-07-01 11:18:06 +02:00
|
|
|
// LCOV_EXCL_START
|
2023-12-15 14:28:15 +01:00
|
|
|
if (Image->HiiInfo.Data != NULL) {
|
2024-07-01 11:18:06 +02:00
|
|
|
// LCOV_EXCL_STOP
|
2023-12-15 14:28:15 +01:00
|
|
|
FreePool (Image->HiiInfo.Data);
|
|
|
|
}
|
|
|
|
|
2024-07-01 11:18:06 +02:00
|
|
|
// LCOV_EXCL_START
|
2023-12-15 14:28:15 +01:00
|
|
|
if (Image->RelocInfo.Relocs != NULL) {
|
2024-07-01 11:18:06 +02:00
|
|
|
// LCOV_EXCL_STOP
|
2023-12-15 14:28:15 +01:00
|
|
|
FreePool (Image->RelocInfo.Relocs);
|
|
|
|
}
|
|
|
|
|
2024-07-01 11:18:06 +02:00
|
|
|
// LCOV_EXCL_START
|
2023-12-15 14:28:15 +01:00
|
|
|
if (Image->DebugInfo.SymbolsPath != NULL) {
|
2024-07-01 11:18:06 +02:00
|
|
|
// LCOV_EXCL_STOP
|
2023-12-15 14:28:15 +01:00
|
|
|
FreePool (Image->DebugInfo.SymbolsPath);
|
|
|
|
}
|
2023-06-26 12:23:02 +02:00
|
|
|
|
|
|
|
memset (Image, 0, sizeof (*Image));
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
ToolImageRelocate (
|
|
|
|
image_tool_image_info_t *Image,
|
2023-12-15 14:28:15 +01:00
|
|
|
uint64_t BaseAddress,
|
|
|
|
uint32_t IgnorePrefix
|
2023-06-26 12:23:02 +02:00
|
|
|
)
|
|
|
|
{
|
2023-12-15 14:28:15 +01:00
|
|
|
const image_tool_segment_t *LastSegment;
|
|
|
|
uint32_t ImageSize;
|
2023-06-26 12:23:02 +02:00
|
|
|
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;
|
|
|
|
|
2023-12-15 14:28:15 +01:00
|
|
|
if (!IS_ALIGNED (BaseAddress, Image->SegmentInfo.SegmentAlignment)) {
|
|
|
|
DEBUG_RAISE ();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2023-06-26 12:23:02 +02:00
|
|
|
Adjust = BaseAddress - Image->HeaderInfo.BaseAddress;
|
|
|
|
|
|
|
|
if (Adjust == 0) {
|
2023-12-15 14:28:15 +01:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
LastSegment = &Image->SegmentInfo.Segments[Image->SegmentInfo.NumSegments - 1];
|
|
|
|
ImageSize = LastSegment->ImageAddress + LastSegment->ImageSize;
|
|
|
|
|
|
|
|
//
|
|
|
|
// When removing the image header prefix, BaseAddress + ImageSize may indeed
|
|
|
|
// overflow. The important part is that the address starting from the first
|
|
|
|
// image segment does not.
|
|
|
|
//
|
|
|
|
if (BaseAddress + ImageSize < BaseAddress + IgnorePrefix) {
|
|
|
|
DEBUG_RAISE ();
|
|
|
|
return false;
|
2023-06-26 12:23:02 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
for (Index = 0; Index < Image->RelocInfo.NumRelocs; ++Index) {
|
|
|
|
Reloc = &Image->RelocInfo.Relocs[Index];
|
|
|
|
|
|
|
|
RelocOffset = Reloc->Target;
|
|
|
|
Segment = ImageGetSegmentByAddress (
|
|
|
|
&RelocOffset,
|
|
|
|
&RemainingSize,
|
|
|
|
&Image->SegmentInfo
|
|
|
|
);
|
2023-12-15 14:28:15 +01:00
|
|
|
assert (Segment != NULL);
|
2023-06-26 12:23:02 +02:00
|
|
|
|
2024-07-01 11:18:06 +02:00
|
|
|
// LCOV_EXCL_START
|
2023-06-26 12:23:02 +02:00
|
|
|
switch (Reloc->Type) {
|
2024-07-01 11:18:06 +02:00
|
|
|
// LCOV_EXCL_STOP
|
2023-06-26 12:23:02 +02:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2023-12-15 14:28:15 +01:00
|
|
|
#if 0
|
2023-06-26 12:23:02 +02:00
|
|
|
case EFI_IMAGE_REL_BASED_ARM_MOV32T:
|
|
|
|
{
|
|
|
|
assert (RemainingSize >= sizeof (UINT32));
|
|
|
|
assert (IS_ALIGNED (Reloc->Target, ALIGNOF (UINT16)));
|
|
|
|
|
|
|
|
PeCoffThumbMovwMovtImmediateFixup (&Segment->Data[RelocOffset], Adjust);
|
|
|
|
break;
|
|
|
|
}
|
2023-12-15 14:28:15 +01:00
|
|
|
#endif
|
2023-06-26 12:23:02 +02:00
|
|
|
|
2024-07-01 11:18:06 +02:00
|
|
|
// LCOV_EXCL_START
|
2023-06-26 12:23:02 +02:00
|
|
|
default:
|
|
|
|
{
|
2023-12-15 14:28:15 +01:00
|
|
|
assert (false);
|
2023-06-26 12:23:02 +02:00
|
|
|
return false;
|
|
|
|
}
|
2024-07-01 11:18:06 +02:00
|
|
|
// LCOV_EXCL_STOP
|
2023-06-26 12:23:02 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Image->HeaderInfo.BaseAddress = BaseAddress;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
static
|
|
|
|
int
|
|
|
|
ToolImageRelocCompare (
|
|
|
|
IN const void *Buffer1,
|
|
|
|
IN const void *Buffer2
|
|
|
|
)
|
|
|
|
{
|
|
|
|
const image_tool_reloc_t *Reloc1;
|
|
|
|
const image_tool_reloc_t *Reloc2;
|
|
|
|
|
|
|
|
Reloc1 = (const image_tool_reloc_t *)Buffer1;
|
|
|
|
Reloc2 = (const image_tool_reloc_t *)Buffer2;
|
|
|
|
|
|
|
|
if (Reloc1->Target < Reloc2->Target) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (Reloc1->Target > Reloc2->Target) {
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
ToolImageSortRelocs (
|
|
|
|
image_tool_image_info_t *Image
|
|
|
|
)
|
|
|
|
{
|
|
|
|
if (Image->RelocInfo.Relocs == NULL) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
qsort (
|
|
|
|
Image->RelocInfo.Relocs,
|
|
|
|
Image->RelocInfo.NumRelocs,
|
|
|
|
sizeof (*Image->RelocInfo.Relocs),
|
|
|
|
ToolImageRelocCompare
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
ToolImageCompare (
|
2024-07-01 11:18:06 +02:00
|
|
|
const image_tool_image_info_t *DestImage,
|
|
|
|
const image_tool_image_info_t *SourceImage
|
2023-06-26 12:23:02 +02:00
|
|
|
)
|
|
|
|
{
|
|
|
|
int CmpResult;
|
|
|
|
uint32_t SegIndex;
|
2024-07-01 11:18:06 +02:00
|
|
|
const char *DestName;
|
|
|
|
const char *SourceName;
|
2023-06-26 12:23:02 +02:00
|
|
|
uint32_t NameIndex;
|
|
|
|
|
|
|
|
//
|
|
|
|
// Compare HeaderInfo.
|
|
|
|
//
|
|
|
|
|
|
|
|
CmpResult = memcmp (
|
2024-07-01 11:18:06 +02:00
|
|
|
&DestImage->HeaderInfo,
|
|
|
|
&SourceImage->HeaderInfo,
|
|
|
|
sizeof (DestImage->HeaderInfo)
|
2023-06-26 12:23:02 +02:00
|
|
|
);
|
2024-07-01 11:18:06 +02:00
|
|
|
// LCOV_EXCL_START
|
2023-06-26 12:23:02 +02:00
|
|
|
if (CmpResult != 0) {
|
2023-12-15 14:28:15 +01:00
|
|
|
DEBUG_RAISE ();
|
2023-06-26 12:23:02 +02:00
|
|
|
return false;
|
|
|
|
}
|
2024-07-01 11:18:06 +02:00
|
|
|
// LCOV_EXCL_STOP
|
2023-06-26 12:23:02 +02:00
|
|
|
|
|
|
|
//
|
|
|
|
// Compare SegmentInfo.
|
|
|
|
// UnpaddedSize is deliberately omitted, as it's implicit by the equality of
|
|
|
|
// ImageSize and Data.
|
|
|
|
//
|
|
|
|
|
|
|
|
CmpResult = memcmp (
|
2024-07-01 11:18:06 +02:00
|
|
|
&DestImage->SegmentInfo,
|
|
|
|
&SourceImage->SegmentInfo,
|
2023-06-26 12:23:02 +02:00
|
|
|
OFFSET_OF (image_tool_segment_info_t, Segments)
|
|
|
|
);
|
2024-07-01 11:18:06 +02:00
|
|
|
// LCOV_EXCL_START
|
2023-06-26 12:23:02 +02:00
|
|
|
if (CmpResult != 0) {
|
2023-12-15 14:28:15 +01:00
|
|
|
DEBUG_RAISE ();
|
2023-06-26 12:23:02 +02:00
|
|
|
return false;
|
|
|
|
}
|
2024-07-01 11:18:06 +02:00
|
|
|
// LCOV_EXCL_STOP
|
2023-06-26 12:23:02 +02:00
|
|
|
|
2024-07-01 11:18:06 +02:00
|
|
|
for (SegIndex = 0; SegIndex < DestImage->SegmentInfo.NumSegments; ++SegIndex) {
|
2023-06-26 12:23:02 +02:00
|
|
|
CmpResult = memcmp (
|
2024-07-01 11:18:06 +02:00
|
|
|
&DestImage->SegmentInfo.Segments[SegIndex],
|
|
|
|
&SourceImage->SegmentInfo.Segments[SegIndex],
|
2023-06-26 12:23:02 +02:00
|
|
|
OFFSET_OF (image_tool_segment_t, Name)
|
|
|
|
);
|
2024-07-01 11:18:06 +02:00
|
|
|
// LCOV_EXCL_START
|
2023-06-26 12:23:02 +02:00
|
|
|
if (CmpResult != 0) {
|
2023-12-15 14:28:15 +01:00
|
|
|
DEBUG_RAISE ();
|
2023-06-26 12:23:02 +02:00
|
|
|
return false;
|
|
|
|
}
|
2024-07-01 11:18:06 +02:00
|
|
|
// LCOV_EXCL_STOP
|
2023-06-26 12:23:02 +02:00
|
|
|
|
|
|
|
//
|
|
|
|
// Don't assume images generally support arbitrarily long names or names in
|
|
|
|
// general. Check prefix equiality as a best effort.
|
|
|
|
//
|
2024-07-01 11:18:06 +02:00
|
|
|
DestName = DestImage->SegmentInfo.Segments[SegIndex].Name;
|
|
|
|
SourceName = SourceImage->SegmentInfo.Segments[SegIndex].Name;
|
|
|
|
|
|
|
|
// LCOV_EXCL_START
|
|
|
|
if (DestName != NULL && SourceName == NULL) {
|
|
|
|
assert (false);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
// LCOV_EXCL_STOP
|
|
|
|
|
|
|
|
//
|
|
|
|
// When omitting the debug info, some file formats (e.g., UE) may not
|
|
|
|
// contain segment names.
|
|
|
|
//
|
|
|
|
if (DestName != NULL) {
|
2023-06-26 12:23:02 +02:00
|
|
|
for (
|
|
|
|
NameIndex = 0;
|
2024-07-01 11:18:06 +02:00
|
|
|
DestName[NameIndex] != '\0' &&
|
|
|
|
// LCOV_EXCL_START
|
|
|
|
SourceName[NameIndex] != '\0';
|
|
|
|
// LCOV_EXCL_STOP
|
2023-06-26 12:23:02 +02:00
|
|
|
++NameIndex
|
|
|
|
) {
|
2024-07-01 11:18:06 +02:00
|
|
|
// LCOV_EXCL_START
|
|
|
|
if (DestName[NameIndex] != SourceName[NameIndex]) {
|
2023-12-15 14:28:15 +01:00
|
|
|
DEBUG_RAISE ();
|
2023-06-26 12:23:02 +02:00
|
|
|
return false;
|
|
|
|
}
|
2024-07-01 11:18:06 +02:00
|
|
|
// LCOV_EXCL_STOP
|
2023-06-26 12:23:02 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-07-01 11:18:06 +02:00
|
|
|
if (DestImage->SegmentInfo.Segments[SegIndex].ImageSize != 0) {
|
2023-12-15 14:28:15 +01:00
|
|
|
CmpResult = memcmp (
|
2024-07-01 11:18:06 +02:00
|
|
|
DestImage->SegmentInfo.Segments[SegIndex].Data,
|
|
|
|
SourceImage->SegmentInfo.Segments[SegIndex].Data,
|
|
|
|
DestImage->SegmentInfo.Segments[SegIndex].ImageSize
|
2023-12-15 14:28:15 +01:00
|
|
|
);
|
2024-07-01 11:18:06 +02:00
|
|
|
// LCOV_EXCL_START
|
2023-12-15 14:28:15 +01:00
|
|
|
if (CmpResult != 0) {
|
|
|
|
DEBUG_RAISE ();
|
|
|
|
return false;
|
|
|
|
}
|
2024-07-01 11:18:06 +02:00
|
|
|
// LCOV_EXCL_STOP
|
2023-06-26 12:23:02 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// Compare RelocInfo.
|
|
|
|
//
|
|
|
|
|
|
|
|
CmpResult = memcmp (
|
2024-07-01 11:18:06 +02:00
|
|
|
&DestImage->RelocInfo,
|
|
|
|
&SourceImage->RelocInfo,
|
2023-06-26 12:23:02 +02:00
|
|
|
OFFSET_OF (image_tool_reloc_info_t, Relocs)
|
|
|
|
);
|
2024-07-01 11:18:06 +02:00
|
|
|
// LCOV_EXCL_START
|
2023-06-26 12:23:02 +02:00
|
|
|
if (CmpResult != 0) {
|
2023-12-15 14:28:15 +01:00
|
|
|
DEBUG_RAISE ();
|
2023-06-26 12:23:02 +02:00
|
|
|
return false;
|
|
|
|
}
|
2024-07-01 11:18:06 +02:00
|
|
|
// LCOV_EXCL_STOP
|
2023-06-26 12:23:02 +02:00
|
|
|
|
2024-07-01 11:18:06 +02:00
|
|
|
if (DestImage->RelocInfo.NumRelocs != 0) {
|
2023-12-15 14:28:15 +01:00
|
|
|
CmpResult = memcmp (
|
2024-07-01 11:18:06 +02:00
|
|
|
DestImage->RelocInfo.Relocs,
|
|
|
|
SourceImage->RelocInfo.Relocs,
|
|
|
|
DestImage->RelocInfo.NumRelocs * sizeof (*DestImage->RelocInfo.Relocs)
|
2023-12-15 14:28:15 +01:00
|
|
|
);
|
2024-07-01 11:18:06 +02:00
|
|
|
// LCOV_EXCL_START
|
2023-12-15 14:28:15 +01:00
|
|
|
if (CmpResult != 0) {
|
|
|
|
DEBUG_RAISE ();
|
|
|
|
return false;
|
|
|
|
}
|
2024-07-01 11:18:06 +02:00
|
|
|
// LCOV_EXCL_STOP
|
2023-06-26 12:23:02 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// Compare HiiInfo.
|
|
|
|
//
|
|
|
|
|
|
|
|
CmpResult = memcmp (
|
2024-07-01 11:18:06 +02:00
|
|
|
&DestImage->HiiInfo,
|
|
|
|
&SourceImage->HiiInfo,
|
2023-06-26 12:23:02 +02:00
|
|
|
OFFSET_OF (image_tool_hii_info_t, Data)
|
|
|
|
);
|
2024-07-01 11:18:06 +02:00
|
|
|
// LCOV_EXCL_START
|
2023-06-26 12:23:02 +02:00
|
|
|
if (CmpResult != 0) {
|
2023-12-15 14:28:15 +01:00
|
|
|
DEBUG_RAISE ();
|
2023-06-26 12:23:02 +02:00
|
|
|
return false;
|
|
|
|
}
|
2024-07-01 11:18:06 +02:00
|
|
|
// LCOV_EXCL_STOP
|
2023-06-26 12:23:02 +02:00
|
|
|
|
2024-07-01 11:18:06 +02:00
|
|
|
// LCOV_EXCL_START
|
|
|
|
if (DestImage->HiiInfo.DataSize != 0) {
|
2023-12-15 14:28:15 +01:00
|
|
|
CmpResult = memcmp (
|
2024-07-01 11:18:06 +02:00
|
|
|
DestImage->HiiInfo.Data,
|
|
|
|
SourceImage->HiiInfo.Data,
|
|
|
|
DestImage->HiiInfo.DataSize
|
2023-12-15 14:28:15 +01:00
|
|
|
);
|
|
|
|
if (CmpResult != 0) {
|
|
|
|
DEBUG_RAISE ();
|
|
|
|
return false;
|
|
|
|
}
|
2023-06-26 12:23:02 +02:00
|
|
|
}
|
2024-07-01 11:18:06 +02:00
|
|
|
// LCOV_EXCL_STOP
|
2023-06-26 12:23:02 +02:00
|
|
|
|
|
|
|
//
|
|
|
|
// Compare DebugInfo.
|
|
|
|
//
|
|
|
|
|
|
|
|
CmpResult = memcmp (
|
2024-07-01 11:18:06 +02:00
|
|
|
&DestImage->DebugInfo,
|
|
|
|
&SourceImage->DebugInfo,
|
2023-06-26 12:23:02 +02:00
|
|
|
OFFSET_OF (image_tool_debug_info_t, SymbolsPath)
|
|
|
|
);
|
2024-07-01 11:18:06 +02:00
|
|
|
// LCOV_EXCL_START
|
2023-06-26 12:23:02 +02:00
|
|
|
if (CmpResult != 0) {
|
2023-12-15 14:28:15 +01:00
|
|
|
DEBUG_RAISE ();
|
2023-06-26 12:23:02 +02:00
|
|
|
return false;
|
|
|
|
}
|
2024-07-01 11:18:06 +02:00
|
|
|
// LCOV_EXCL_STOP
|
2023-06-26 12:23:02 +02:00
|
|
|
|
2024-07-01 11:18:06 +02:00
|
|
|
// LCOV_EXCL_START
|
|
|
|
if ((DestImage->DebugInfo.SymbolsPath != NULL) != (SourceImage->DebugInfo.SymbolsPath != NULL)) {
|
2023-12-15 14:28:15 +01:00
|
|
|
DEBUG_RAISE ();
|
2023-06-26 12:23:02 +02:00
|
|
|
return false;
|
|
|
|
}
|
2024-07-01 11:18:06 +02:00
|
|
|
// LCOV_EXCL_STOP
|
2023-06-26 12:23:02 +02:00
|
|
|
|
2024-07-01 11:18:06 +02:00
|
|
|
if (DestImage->DebugInfo.SymbolsPath != NULL) {
|
2023-06-26 12:23:02 +02:00
|
|
|
CmpResult = strcmp (
|
2024-07-01 11:18:06 +02:00
|
|
|
DestImage->DebugInfo.SymbolsPath,
|
|
|
|
SourceImage->DebugInfo.SymbolsPath
|
2023-06-26 12:23:02 +02:00
|
|
|
);
|
2024-07-01 11:18:06 +02:00
|
|
|
// LCOV_EXCL_START
|
2023-06-26 12:23:02 +02:00
|
|
|
if (CmpResult != 0) {
|
2023-12-15 14:28:15 +01:00
|
|
|
DEBUG_RAISE ();
|
2023-06-26 12:23:02 +02:00
|
|
|
return false;
|
|
|
|
}
|
2024-07-01 11:18:06 +02:00
|
|
|
// LCOV_EXCL_STOP
|
2023-06-26 12:23:02 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
ToolImageStripRelocs (
|
|
|
|
image_tool_image_info_t *Image
|
|
|
|
)
|
|
|
|
{
|
|
|
|
Image->RelocInfo.NumRelocs = 0;
|
2023-12-15 14:28:15 +01:00
|
|
|
|
|
|
|
if (Image->RelocInfo.Relocs != NULL) {
|
|
|
|
FreePool (Image->RelocInfo.Relocs);
|
|
|
|
}
|
|
|
|
|
2023-06-26 12:23:02 +02:00
|
|
|
Image->RelocInfo.Relocs = NULL;
|
|
|
|
|
|
|
|
Image->RelocInfo.RelocsStripped = TRUE;
|
|
|
|
}
|