mirror of
https://github.com/revng/revng
synced 2026-06-21 14:07:57 +00:00
Import sections into segment's struct
Each model::Segment is associated to a model::StructType. Now we also create sub-`structs` for sections, if available.
This commit is contained in:
committed by
Pietro Fezzardi
parent
95aa074e4c
commit
b34031f828
@@ -6,6 +6,7 @@
|
||||
|
||||
#include "revng/Model/Binary.h"
|
||||
#include "revng/Model/QualifiedType.h"
|
||||
#include "revng/Model/Section.h"
|
||||
#include "revng/Support/Assert.h"
|
||||
#include "revng/Support/IRHelpers.h"
|
||||
#include "revng/Support/MetaAddress.h"
|
||||
@@ -21,55 +22,97 @@ struct DataSymbol {
|
||||
bool operator==(const DataSymbol &) const = default;
|
||||
};
|
||||
|
||||
using DataSymbolVecTy = llvm::SmallVectorImpl<DataSymbol>;
|
||||
|
||||
inline bool checkForOverlap(const model::StructType &Struct,
|
||||
const model::StructField &Field) {
|
||||
uint64_t Size = *Field.Type().size();
|
||||
uint64_t Offset,
|
||||
uint64_t Size) {
|
||||
for (auto &Current : Struct.Fields()) {
|
||||
uint64_t CurrentSize = *Current.Type().size();
|
||||
if ((Current.Offset() < Field.Offset() + Size))
|
||||
if (Current.Offset() + CurrentSize > Field.Offset())
|
||||
if ((Current.Offset() < Offset + Size))
|
||||
if (Current.Offset() + CurrentSize > Offset)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
inline model::TypePath populateSegmentTypeStruct(model::Binary &Binary,
|
||||
model::Segment &Segment,
|
||||
DataSymbolVecTy &DataSymbols) {
|
||||
model::TypePath StructPath = createEmptyStruct(Binary, Segment.VirtualSize());
|
||||
auto *Struct = llvm::cast<model::StructType>(StructPath.get());
|
||||
inline void importSymbolsInto(model::Binary &Binary,
|
||||
llvm::SmallVector<DataSymbol, 32> &DataSymbols,
|
||||
model::StructType *Struct,
|
||||
MetaAddress StructStartAddress) {
|
||||
MetaAddress StructEndAddress = StructStartAddress + Struct->Size();
|
||||
if (not StructEndAddress.isValid())
|
||||
return;
|
||||
|
||||
for (const auto &DataSymbol : DataSymbols) {
|
||||
const auto &[Address, Size, Name] = DataSymbol;
|
||||
for (auto It = DataSymbols.begin(); It != DataSymbols.end(); ++It) {
|
||||
const auto &[SymbolStartAddress, SymbolSize, SymbolName] = *It;
|
||||
MetaAddress SymbolEndAddress = SymbolStartAddress + SymbolSize;
|
||||
|
||||
if (Segment.contains(Address)) {
|
||||
auto Offset = Address - Segment.StartAddress();
|
||||
if (SymbolEndAddress.isValid()
|
||||
and SymbolStartAddress.addressGreaterThanOrEqual(StructStartAddress)
|
||||
and SymbolEndAddress.addressLowerThanOrEqual(StructEndAddress)) {
|
||||
auto Offset = SymbolStartAddress - StructStartAddress;
|
||||
revng_assert(Offset.has_value());
|
||||
|
||||
model::QualifiedType FieldType;
|
||||
// Discard any symbols that would overlap an already existing one.
|
||||
if (checkForOverlap(*Struct, *Offset, SymbolSize)) {
|
||||
It = std::prev(DataSymbols.erase(It));
|
||||
continue;
|
||||
}
|
||||
|
||||
model::TypePath T;
|
||||
|
||||
if (Size == 1 || Size == 2 || Size == 4 || Size == 8) {
|
||||
T = Binary.getPrimitiveType(model::PrimitiveTypeKind::Generic, Size);
|
||||
FieldType = { T, {} };
|
||||
if (SymbolSize == 1 || SymbolSize == 2 || SymbolSize == 4
|
||||
|| SymbolSize == 8) {
|
||||
T = Binary.getPrimitiveType(model::PrimitiveTypeKind::Generic,
|
||||
SymbolSize);
|
||||
} else {
|
||||
// Replace non-standardly sized types with an array of bytes
|
||||
T = Binary.getPrimitiveType(model::PrimitiveTypeKind::Generic, 1);
|
||||
FieldType = { T, { { model::QualifierKind::Array, Size } } };
|
||||
// If the symbol has a non-standard size, make it an empty struct with
|
||||
// the same size instead.
|
||||
T = createEmptyStruct(Binary, SymbolSize);
|
||||
}
|
||||
|
||||
model::StructField Field{ *Offset, {}, Name.str(), {}, FieldType };
|
||||
if (!checkForOverlap(*Struct, Field)) {
|
||||
// Discard any symbols that would overlap an already existing one.
|
||||
const auto &[_, Success] = Struct->Fields().insert(Field);
|
||||
revng_assert(Success);
|
||||
}
|
||||
model::QualifiedType FieldType = { T, {} };
|
||||
model::StructField Field{ *Offset, {}, SymbolName.str(), {}, FieldType };
|
||||
const auto &[_, Success] = Struct->Fields().insert(Field);
|
||||
revng_assert(Success);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
revng_assert(Struct->verify());
|
||||
return StructPath;
|
||||
inline model::TypePath
|
||||
populateSegmentTypeStruct(model::Binary &Binary,
|
||||
model::Segment &Segment,
|
||||
llvm::SmallVector<DataSymbol, 32> DataSymbols) {
|
||||
using namespace llvm;
|
||||
using namespace model;
|
||||
|
||||
// Create a struct for the segment
|
||||
TypePath SegmentStructPath = createEmptyStruct(Binary, Segment.VirtualSize());
|
||||
auto *SegmentStruct = cast<model::StructType>(SegmentStructPath.get());
|
||||
|
||||
for (model::Section &Section : Segment.Sections()) {
|
||||
auto Offset = Section.StartAddress() - Segment.StartAddress();
|
||||
revng_assert(Offset.has_value());
|
||||
|
||||
// Create a struct for each section
|
||||
TypePath SectionStructPath = createEmptyStruct(Binary, Section.Size());
|
||||
auto *SectionStruct = cast<model::StructType>(SectionStructPath.get());
|
||||
|
||||
// Import (and consume) symbols that fall within such section
|
||||
importSymbolsInto(Binary,
|
||||
DataSymbols,
|
||||
SectionStruct,
|
||||
Section.StartAddress());
|
||||
|
||||
// Insert the field the segment struct
|
||||
StructField SectionField{
|
||||
*Offset, {}, Section.Name(), {}, { SectionStructPath, {} }
|
||||
};
|
||||
SegmentStruct->Fields().insert(SectionField);
|
||||
}
|
||||
|
||||
// Pour the remaining symbols into the segment struct
|
||||
importSymbolsInto(Binary, DataSymbols, SegmentStruct, Segment.StartAddress());
|
||||
|
||||
revng_assert(SegmentStruct->verify());
|
||||
return SegmentStructPath;
|
||||
}
|
||||
|
||||
@@ -4,12 +4,8 @@
|
||||
|
||||
---
|
||||
Segments:
|
||||
- Type: "/Types/12084688553483582712-StructType"
|
||||
- Type: "/Types/1815-StructType"
|
||||
Types:
|
||||
- Kind: PrimitiveType
|
||||
ID: 513
|
||||
PrimitiveKind: Generic
|
||||
Size: 1
|
||||
- Kind: PrimitiveType
|
||||
ID: 516
|
||||
PrimitiveKind: Generic
|
||||
@@ -19,16 +15,22 @@ Types:
|
||||
PrimitiveKind: Generic
|
||||
Size: 8
|
||||
- Kind: StructType
|
||||
ID: 12084688553483582712
|
||||
ID: 1815
|
||||
Size: 92
|
||||
Fields:
|
||||
- Offset: 0
|
||||
CustomName: "unreserved__custom_data"
|
||||
OriginalName: .custom_data
|
||||
Type:
|
||||
UnqualifiedType: "/Types/1816-StructType"
|
||||
- Kind: StructType
|
||||
ID: 1816
|
||||
Size: 92
|
||||
Fields:
|
||||
- Offset: 0
|
||||
OriginalName: char_80_global
|
||||
Type:
|
||||
UnqualifiedType: "/Types/513-PrimitiveType"
|
||||
Qualifiers:
|
||||
- Kind: Array
|
||||
Size: 80
|
||||
UnqualifiedType: "/Types/1817-StructType"
|
||||
- Offset: 80
|
||||
OriginalName: uint64_global
|
||||
Type:
|
||||
@@ -37,3 +39,7 @@ Types:
|
||||
OriginalName: uint32_global
|
||||
Type:
|
||||
UnqualifiedType: "/Types/516-PrimitiveType"
|
||||
- Kind: StructType
|
||||
ID: 1817
|
||||
Size: 80
|
||||
Fields: []
|
||||
|
||||
Reference in New Issue
Block a user