I understand it now. The article at
<http://www.debuginfo.com/articles/debuginfomatch.html> was of great help.

On 07/05/17 15:29, Laszlo Ersek wrote:
> On 07/05/17 14:42, Laszlo Ersek wrote:
>> On 07/03/17 07:21, Liming Gao wrote:

>>> @@ -2886,11 +2891,23 @@ Returns:
>>>
>>>    if (DebugDirectoryEntryFileOffset != 0) {
>>>      DebugEntry = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *) (FileBuffer + 
>>> DebugDirectoryEntryFileOffset);
>>> -    DebugEntry->TimeDateStamp = 0;
>>> -    mImageTimeStamp = 0;
>>> -    if (ZeroDebugFlag) {
>>> -      memset (FileBuffer + DebugEntry->FileOffset, 0, 
>>> DebugEntry->SizeOfData);
>>> -      memset (DebugEntry, 0, sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY));
>>> +    Index = 0;
>>> +    for (Index=0; Index < DebugDirectoryEntrySize / sizeof 
>>> (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY); Index ++, DebugEntry ++) {
>>> +      DebugEntry->TimeDateStamp = 0;
>>> +      if (ZeroDebugFlag || DebugEntry->Type != 
>>> EFI_IMAGE_DEBUG_TYPE_CODEVIEW) {
>>> +        memset (FileBuffer + DebugEntry->FileOffset, 0, 
>>> DebugEntry->SizeOfData);
>>
>> This memset() is the culprit.
>>
>> According to gdb (all values decimal),
>> - Index = 1,
>> - DebugDirectoryEntrySize = 237,
>> - ZeroDebugFlag = 0.
>>
>> These values look suspicious, because
>> sizeof(EFI_IMAGE_DEBUG_DIRECTORY_ENTRY) is 28, and
>> DebugDirectoryEntrySize (237) is not an integral multiple of that.
>>
>> This is the first EFI_IMAGE_DEBUG_DIRECTORY_ENTRY element:
>>
>>> (gdb) print ((EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *) (FileBuffer + 
>>> DebugDirectoryEntryFileOffset))[0]
>>> $11 = {Characteristics = 0, TimeDateStamp = 0, MajorVersion = 0, 
>>> MinorVersion = 0, Type = 2, SizeOfData = 209, RVA = 33292, FileOffset = 
>>> 33292}

Notice this. The first entry (which is valid, with type =
EFI_IMAGE_DEBUG_TYPE_CODEVIEW), points at offset 33292, and the
pointed-to data (which is a CodeView information block) has size 209.
This means that the first byte *past* the CodeView information is at
offset 33292 + 209 = 33501.

Now, look at the data dictionary again:

>>> (gdb) print Optional64Hdr->DataDirectory
>>> $22 = {{VirtualAddress = 0,     Size = 0},    // 
>>> EFI_IMAGE_DIRECTORY_ENTRY_EXPORT
>>>        {VirtualAddress = 0,     Size = 0},    // 
>>> EFI_IMAGE_DIRECTORY_ENTRY_IMPORT
>>>        {VirtualAddress = 0,     Size = 0},    // 
>>> EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
>>>        {VirtualAddress = 0,     Size = 0},    // 
>>> EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
>>>        {VirtualAddress = 0,     Size = 0},    // 
>>> EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
>>>        {VirtualAddress = 36864, Size = 4096}, // 
>>> EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
>>>        {VirtualAddress = 33264, Size = 237},  // 
>>> EFI_IMAGE_DIRECTORY_ENTRY_DEBUG

Notice this: 33264 + 237 = 33501. The same end offset!

And then: 237 - 209 = 28, which is exactly the size of
EFI_IMAGE_DEBUG_DIRECTORY_ENTRY.

So, what happens is that the GNU linker (or some other bin-util that
produces the input file for GenFw)

(1) creates a valid EFI_IMAGE_DEBUG_DIRECTORY_ENTRY, of type
EFI_IMAGE_DEBUG_TYPE_CODEVIEW, with size = 28,

(2) this element points to a valid CV_INFO_PDB20 structure (having NB10
for signature), with size = 209,

(3) The CV_INFO_PDB20 structure *immediately* follows the
EFI_IMAGE_DEBUG_DIRECTORY_ENTRY element that points to it -- this is all
fine,

(4) *however*, the pointed-to CV_INFO_PDB20 element (from (3)) is *also*
included in the size of the debug directory, even though the size of the
debug directory should *only* describe the debug directory entry from (1)!

So, this is most certainly a GNU Binutils bug.

We can catch it though: as soon as we find an
EFI_IMAGE_DEBUG_DIRECTORY_ENTRY whose FileOffset field points into the
debug directory itself, we know that the debug directory's size has to
be truncated at once to that offset.

Let me see if I can write a patch for this.

Thanks
Laszlo

_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel

Reply via email to