Merge remote-tracking branch 'origin/GP-5160_ghintern_coff_align--SQUASHED'

This commit is contained in:
Ryan Kurtz
2024-12-17 11:34:54 -05:00
3 changed files with 56 additions and 30 deletions
@@ -4,9 +4,9 @@
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -175,8 +175,10 @@ public class SectionHeader implements StructConverter, ByteArrayConverter {
* Align on 8192-byte boundary.
*/
public final static int IMAGE_SCN_ALIGN_8192BYTES = 0x00E00000;
// Unused = 0x00F00000;
// public final static int IMAGE_SCN_ALIGN_MASK = 0x00F00000;
/**
* Mask for alignment flags
*/
public final static int IMAGE_SCN_ALIGN_MASK = 0x00F00000;
/**
* Section contains extended relocations.
*/
@@ -4,9 +4,9 @@
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -538,7 +538,7 @@ public class CoffLoader extends AbstractLibrarySupportLoader {
Map<CoffSectionHeader, Address> map) {
// 1. loop over all sections
// put all sections not at 0 into address set
// put all sections at 0 into "totals" map
// put all sections at 0 into "totals" map, accounting for later alignment needs
// 2. look for space before minimum of taken addresses
// 3. or, look for space after maximum of taken addresses
@@ -548,24 +548,22 @@ public class CoffLoader extends AbstractLibrarySupportLoader {
AddressSet nonZeroSet = new AddressSet();
int totalSize = 0;
TreeMap<String, Integer> zeroSectionSizes = new TreeMap<>();
TreeMap<String, Integer> zeroSectionOffsets = new TreeMap<>();
int totalZeroSectionSize = 0;
Map<String, Integer> zeroSectionSizes = new TreeMap<>();
Map<String, Integer> zeroSectionOffsets = new TreeMap<>();
List<CoffSectionHeader> sections = header.getSections();
for (CoffSectionHeader section : sections) {
int physicalAddress = section.getPhysicalAddress();
int size = section.getSize(language);
if (physicalAddress == 0) {
// We don't know the exact offset now, so assume worst-case alignment penalty
int alignedSize = size + getSectionAlignment(section) - 1;
String name = section.getName();
Integer s = zeroSectionSizes.get(name);
if (s == null) {
zeroSectionSizes.put(name, size);
}
else {
zeroSectionSizes.put(name, s + size);
}
totalSize += size;
zeroSectionSizes.compute(name,
(k, v) -> (v == null ? alignedSize : v + alignedSize));
totalZeroSectionSize += alignedSize;
}
else {
if (size > 0) {
@@ -579,35 +577,47 @@ public class CoffLoader extends AbstractLibrarySupportLoader {
}
}
}
Address maxAddress = nonZeroSet.getMaxAddress();
int offset = (maxAddress == null ? EMPTY_START_OFFSET - 1
: (int) (maxAddress.getOffset() & 0xffffffff));
long sum = offset;
sum += totalSize;
sum += totalZeroSectionSize;
if (sum <= 0x100000000L) {
int start = align(offset + 1);
offset += 1;
// Each group of sections with the same name should be aligned at least at 256 bytes
for (Entry<String, Integer> entry : zeroSectionSizes.entrySet()) {
zeroSectionOffsets.put(entry.getKey(), start);
start = align(start + entry.getValue());
offset = (offset + DEFAULT_ALIGNMENT - 1) / DEFAULT_ALIGNMENT * DEFAULT_ALIGNMENT;
zeroSectionOffsets.put(entry.getKey(), offset);
offset += zeroSectionSizes.get(entry.getKey());
}
int sectionNumber = 1;
for (CoffSectionHeader section : sections) {
int physicalAddress = section.getPhysicalAddress();
if (physicalAddress == 0) {
String name = section.getName();
start = zeroSectionOffsets.get(name);
relocateSection(header, section, sectionNumber, start);
zeroSectionOffsets.put(name, start + section.getSize(language));
int alignment = getSectionAlignment(section);
offset = (zeroSectionOffsets.get(name) + alignment - 1) / alignment * alignment;
relocateSection(header, section, sectionNumber, offset);
zeroSectionOffsets.put(name, offset + section.getSize(language));
}
++sectionNumber;
}
}
}
private static final int ALIGNMENT = 0x100;
private static final int DEFAULT_ALIGNMENT = 0x100;
private int align(int i) {
return (i + ALIGNMENT - 1) / ALIGNMENT * ALIGNMENT;
/**
* Query a section header for alignment information. The base version of this method assumes
* no alignment information is stored in the section header. Subclasses may implement a
* platform-specific check for alignment information.
*
* @param section header object for the section
* @return the alignment requested by the section
*/
protected int getSectionAlignment(CoffSectionHeader section) {
return 1;
}
private void relocateSection(CoffFileHeader header, CoffSectionHeader section,
@@ -4,9 +4,9 @@
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -15,6 +15,9 @@
*/
package ghidra.app.util.opinion;
import ghidra.app.util.bin.format.coff.CoffSectionHeader;
import ghidra.app.util.bin.format.pe.SectionHeader;
public class MSCoffLoader extends CoffLoader {
public final static String MSCOFF_NAME = "MS Common Object File Format (COFF)";
@@ -33,4 +36,15 @@ public class MSCoffLoader extends CoffLoader {
return true;
}
@Override
protected int getSectionAlignment(CoffSectionHeader section) {
// Alignment is packed as a 4-bit integer in the flags, value 2^(align_bits - 1)
int s_flags = section.getFlags();
int align_bits = (s_flags & SectionHeader.IMAGE_SCN_ALIGN_MASK) >> 20;
if (align_bits == 0 || align_bits >= 0xF) {
return 1;
}
return 1 << (align_bits - 1);
}
}