@@ -130,6 +130,7 @@ IReadOnlyDictionary<string, TargetPointer> GetLoaderAllocatorHeaps(TargetPointer
130130| ` PEImageLayout ` | ` Base ` | Base address of the image layout |
131131| ` PEImageLayout ` | ` Size ` | Size of the image layout |
132132| ` PEImageLayout ` | ` Flags ` | Flags associated with the PEImageLayout |
133+ | ` PEImageLayout ` | ` Format ` | Format discriminator (PE or Webcil) for the image layout |
133134| ` CGrowableSymbolStream ` | ` Buffer ` | Pointer to the raw symbol stream buffer start |
134135| ` CGrowableSymbolStream ` | ` Size ` | Size of the raw symbol stream buffer |
135136| ` AppDomain ` | ` RootAssembly ` | Pointer to the root assembly |
@@ -168,6 +169,11 @@ IReadOnlyDictionary<string, TargetPointer> GetLoaderAllocatorHeaps(TargetPointer
168169| ` DynamicILBlobTable ` | ` EntrySize ` | Size of each table entry |
169170| ` DynamicILBlobTable ` | ` EntryMethodToken ` | Offset of each entry method token from entry address |
170171| ` DynamicILBlobTable ` | ` EntryIL ` | Offset of each entry IL from entry address |
172+ | ` WebcilHeader ` | ` CoffSections ` | Number of COFF sections in the Webcil image |
173+ | ` WebcilSectionHeader ` | ` VirtualSize ` | Virtual size of the section |
174+ | ` WebcilSectionHeader ` | ` VirtualAddress ` | RVA of the section |
175+ | ` WebcilSectionHeader ` | ` SizeOfRawData ` | Size of the section's raw data |
176+ | ` WebcilSectionHeader ` | ` PointerToRawData ` | File offset to the section's raw data |
171177
172178
173179
@@ -183,6 +189,7 @@ IReadOnlyDictionary<string, TargetPointer> GetLoaderAllocatorHeaps(TargetPointer
183189| --- | --- | --- | --- |
184190| ` ASSEMBLY_NOTIFYFLAGS_PROFILER_NOTIFIED ` | uint | Flag in Assembly NotifyFlags indicating the Assembly will notify profilers. | ` 0x1 ` |
185191| ` DefaultDomainFriendlyName ` | string | Friendly name returned when ` AppDomain.FriendlyName ` is null (matches native ` DEFAULT_DOMAIN_FRIENDLY_NAME ` ) | ` "DefaultDomain" ` |
192+ | ` MaxWebcilSections ` | ushort | Maximum number of COFF sections supported in a Webcil image (must stay in sync with native ` WEBCIL_MAX_SECTIONS ` ) | ` 16 ` |
186193
187194Contracts used:
188195| Contract Name |
@@ -205,6 +212,13 @@ private enum PEImageFlags : uint
205212{
206213 FLAG_MAPPED = 0x 01 , // the file is mapped/hydrated (vs. the raw disk layout)
207214 };
215+
216+ // Must stay in sync with native PEImageLayout::ImageFormat values.
217+ private enum ImageFormat : uint
218+ {
219+ PE = 0 ,
220+ Webcil = 1 ,
221+ }
208222```
209223
210224### Method Implementations
@@ -396,48 +410,90 @@ TargetPointer ILoader.GetILAddr(TargetPointer peAssemblyPtr, int rva)
396410 }
397411 else
398412 {
399- // find NT headers using DOS header
400- uint dosHeaderLfanew = target .Read <uint >(baseAddress + /* ImageDosHeader::LfanewOffset */ );
401- TargetPointer ntHeadersPtr = baseAddress + dosHeaderLfanew ;
413+ offset = RvaToOffset (rva , peImageLayout );
414+ }
415+ return baseAddress + offset ;
416+ }
402417
403- TargetPointer optionalHeaderPtr = ntHeadersPtr + /* ImageNTHeaders::OptionalHeaderOffset */ ;
418+ uint RvaToOffset (int rva , Data .PEImageLayout imageLayout )
419+ {
420+ uint format = target .Read <uint >(imageLayout + /* PEImageLayout::Format offset */ );
421+ if (format == (uint )ImageFormat .Webcil )
422+ return WebcilRvaToOffset (rva , imageLayout );
404423
405- // Get number of sections from file header
406- TargetPointer fileHeaderPtr = ntHeadersPtr + /* ImageNTHeaders::FileHeaderOffset */ ;
407- uint numberOfSections = target .Read <uint >(fileHeaderPtr + /* ImageFileHeader::NumberOfSectionsOffset */ );
424+ TargetPointer baseAddress = target .ReadPointer (imageLayout + /* PEImageLayout::Base offset */ );
408425
409- // Calculate first section address (after NT headers and optional header)
410- uint imageFileHeaderSize = target .Read <ushort >( fileHeaderPtr + /* ImageFileHeader::SizeOfOptionalHeaderOffset */ );
411- TargetPointer firstSectionPtr = ntHeadersPtr + /* ImageNTHeaders::OptionalHeaderOffset */ + imageFileHeaderSize ;
426+ // find NT headers using DOS header
427+ uint dosHeaderLfanew = target .Read <uint >( baseAddress + /* ImageDosHeader::LfanewOffset */ );
428+ TargetPointer ntHeadersPtr = baseAddress + dosHeaderLfanew ;
412429
413- // Find the section containing this RVA
414- TargetPointer sectionPtr = TargetPointer . Null ;
415- uint sectionHeaderSize = /* sizeof(ImageSectionHeader native struct) */ ;
430+ // Get number of sections from file header
431+ TargetPointer fileHeaderPtr = ntHeadersPtr + /* ImageNTHeaders::FileHeaderOffset */ ;
432+ uint numberOfSections = target . Read < uint >( fileHeaderPtr + /* ImageFileHeader::NumberOfSectionsOffset */ ) ;
416433
417- for (uint i = 0 ; i < numberOfSections ; i ++ )
418- {
419- TargetPointer currentSectionPtr = firstSectionPtr + (i * sectionHeaderSize );
420- uint virtualAddress = target .Read <uint >(currentSectionPtr + /* ImageSectionHeader::VirtualAddressOffset */ );
421- uint sizeOfRawData = target .Read <uint >(currentSectionPtr + /* ImageSectionHeader::SizeOfRawDataOffset */ );
434+ // Calculate first section address (after NT headers and optional header)
435+ uint imageFileHeaderSize = target .Read <ushort >(fileHeaderPtr + /* ImageFileHeader::SizeOfOptionalHeaderOffset */ );
436+ TargetPointer firstSectionPtr = ntHeadersPtr + /* ImageNTHeaders::OptionalHeaderOffset */ + imageFileHeaderSize ;
422437
423- if (rva >= VirtualAddress && rva < VirtualAddress + SizeOfRawData )
424- {
425- sectionPtr = currentSectionPtr ;
426- }
427- }
428- if (sectionPtr == TargetPointer .Null )
438+ // Find the section containing this RVA
439+ TargetPointer sectionPtr = TargetPointer .Null ;
440+ uint sectionHeaderSize = /* sizeof(ImageSectionHeader native struct) */ ;
441+
442+ for (uint i = 0 ; i < numberOfSections ; i ++ )
443+ {
444+ TargetPointer currentSectionPtr = firstSectionPtr + (i * sectionHeaderSize );
445+ uint virtualAddress = target .Read <uint >(currentSectionPtr + /* ImageSectionHeader::VirtualAddressOffset */ );
446+ uint sizeOfRawData = target .Read <uint >(currentSectionPtr + /* ImageSectionHeader::SizeOfRawDataOffset */ );
447+
448+ if (rva >= virtualAddress && rva < virtualAddress + sizeOfRawData )
429449 {
430- throw new InvalidOperationException ( " Failed to read from image. " ) ;
450+ sectionPtr = currentSectionPtr ;
431451 }
432- else
452+ }
453+ if (sectionPtr == TargetPointer .Null )
454+ {
455+ throw new InvalidOperationException (" Failed to read from image." );
456+ }
457+
458+ // Convert RVA to file offset using section information
459+ uint sectionVirtualAddress = target .Read <uint >(sectionPtr + /* ImageSectionHeader::VirtualAddressOffset */ );
460+ uint sectionPointerToRawData = target .Read <uint >(sectionPtr + /* ImageSectionHeader::PointerToRawDataOffset */ );
461+ return (rva - sectionVirtualAddress ) + sectionPointerToRawData ;
462+ }
463+
464+ uint WebcilRvaToOffset (int rva , Data .PEImageLayout imageLayout )
465+ {
466+ if (rva < 0 )
467+ throw new InvalidOperationException (" Negative RVA in Webcil image." );
468+
469+ TargetPointer headerBase = imageLayout .Base ;
470+ Data .WebcilHeader webcilHeader = // read WebcilHeader at headerBase
471+ uint webcilHeaderSize = /* sizeof(WebcilHeader) from type info */ ;
472+ uint webcilSectionSize = /* sizeof(WebcilSectionHeader) from type info */ ;
473+
474+ ushort numSections = webcilHeader .CoffSections ;
475+ if (numSections == 0 || numSections > MaxWebcilSections )
476+ throw new InvalidOperationException (" Invalid Webcil section count." );
477+
478+ TargetPointer sectionTableBase = headerBase + webcilHeaderSize ;
479+
480+ for (int i = 0 ; i < numSections ; i ++ )
481+ {
482+ TargetPointer sectionPtr = sectionTableBase + (uint )(i * (int )webcilSectionSize );
483+ Data .WebcilSectionHeader section = // read WebcilSectionHeader at sectionPtr
484+
485+ uint rvaUnsigned = (uint )rva ;
486+ if (rvaUnsigned >= section .VirtualAddress )
433487 {
434- // Convert RVA to file offset using section information
435- uint sectionVirtualAddress = target .Read <uint >(sectionPtr + /* ImageSectionHeader::VirtualAddressOffset */ );
436- uint sectionPointerToRawData = target .Read <uint >(sectionPtr + /* ImageSectionHeader::PointerToRawDataOffset */ );
437- offset = ((rva - sectionVirtualAddress ) + sectionPointerToRawData );
488+ uint offset = rvaUnsigned - section .VirtualAddress ;
489+ if (offset < section .VirtualSize && offset < section .SizeOfRawData )
490+ {
491+ return offset + section .PointerToRawData ;
492+ }
438493 }
439494 }
440- return baseAddress + offset ;
495+
496+ throw new InvalidOperationException (" Failed to resolve RVA in Webcil image." );
441497}
442498
443499bool TryGetSymbolStream (ModuleHandle handle , out TargetPointer buffer , out uint size )
0 commit comments