mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2026-06-01 06:25:26 +08:00
Merge remote-tracking branch 'origin/GP-5160_ghintern_coff_align--SQUASHED'
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user