@@ -131,7 +131,6 @@ class Addressable {
131
131
uint64_t IsAbsolute : 1 ;
132
132
};
133
133
134
- using BlockOrdinal = unsigned ;
135
134
using SectionOrdinal = unsigned ;
136
135
137
136
// / An Addressable with content and edges.
@@ -140,10 +139,9 @@ class Block : public Addressable {
140
139
141
140
private:
142
141
// / Create a zero-fill defined addressable.
143
- Block (Section &Parent, BlockOrdinal Ordinal, JITTargetAddress Size,
144
- JITTargetAddress Address, uint64_t Alignment, uint64_t AlignmentOffset)
145
- : Addressable(Address, true ), Parent(Parent), Size(Size),
146
- Ordinal (Ordinal) {
142
+ Block (Section &Parent, JITTargetAddress Size, JITTargetAddress Address,
143
+ uint64_t Alignment, uint64_t AlignmentOffset)
144
+ : Addressable(Address, true ), Parent(Parent), Size(Size) {
147
145
assert (isPowerOf2_64 (Alignment) && " Alignment must be power of 2" );
148
146
assert (AlignmentOffset < Alignment &&
149
147
" Alignment offset cannot exceed alignment" );
@@ -154,10 +152,10 @@ class Block : public Addressable {
154
152
}
155
153
156
154
// / Create a defined addressable for the given content.
157
- Block (Section &Parent, BlockOrdinal Ordinal, StringRef Content ,
158
- JITTargetAddress Address, uint64_t Alignment, uint64_t AlignmentOffset)
155
+ Block (Section &Parent, StringRef Content, JITTargetAddress Address ,
156
+ uint64_t Alignment, uint64_t AlignmentOffset)
159
157
: Addressable(Address, true ), Parent(Parent), Data(Content.data()),
160
- Size(Content.size()), Ordinal(Ordinal) {
158
+ Size (Content.size()) {
161
159
assert (isPowerOf2_64 (Alignment) && " Alignment must be power of 2" );
162
160
assert (AlignmentOffset < Alignment &&
163
161
" Alignment offset cannot exceed alignment" );
@@ -180,9 +178,6 @@ class Block : public Addressable {
180
178
// / Return the parent section for this block.
181
179
Section &getSection () const { return Parent; }
182
180
183
- // / Return the ordinal for this block.
184
- BlockOrdinal getOrdinal () const { return Ordinal; }
185
-
186
181
// / Returns true if this is a zero-fill block.
187
182
// /
188
183
// / If true, getSize is callable but getContent is not (the content is
@@ -263,7 +258,6 @@ class Block : public Addressable {
263
258
Section &Parent;
264
259
const char *Data = nullptr ;
265
260
size_t Size = 0 ;
266
- BlockOrdinal Ordinal = 0 ;
267
261
std::vector<Edge> Edges;
268
262
};
269
263
@@ -357,6 +351,7 @@ class Symbol {
357
351
JITTargetAddress Size, bool IsCallable,
358
352
bool IsLive) {
359
353
assert (SymStorage && " Storage cannot be null" );
354
+ assert (Offset < Base.getSize () && " Symbol offset is outside block" );
360
355
auto *Sym = reinterpret_cast <Symbol *>(SymStorage);
361
356
new (Sym) Symbol (Base, Offset, StringRef (), Size, Linkage::Strong,
362
357
Scope::Local, IsLive, IsCallable);
@@ -368,6 +363,7 @@ class Symbol {
368
363
JITTargetAddress Size, Linkage L, Scope S,
369
364
bool IsLive, bool IsCallable) {
370
365
assert (SymStorage && " Storage cannot be null" );
366
+ assert (Offset < Base.getSize () && " Symbol offset is outside block" );
371
367
assert (!Name.empty () && " Name cannot be empty" );
372
368
auto *Sym = reinterpret_cast <Symbol *>(SymStorage);
373
369
new (Sym) Symbol (Base, Offset, Name, Size, L, S, IsLive, IsCallable);
@@ -588,9 +584,6 @@ class Section {
588
584
// / Return true if this section contains no symbols.
589
585
bool symbols_empty () const { return Symbols.empty (); }
590
586
591
- // / Returns the ordinal for the next block.
592
- BlockOrdinal getNextBlockOrdinal () { return NextBlockOrdinal++; }
593
-
594
587
private:
595
588
void addSymbol (Symbol &Sym) {
596
589
assert (!Symbols.count (&Sym) && " Symbol is already in this section" );
@@ -615,7 +608,6 @@ class Section {
615
608
StringRef Name;
616
609
sys::Memory::ProtectionFlags Prot;
617
610
SectionOrdinal SecOrdinal = 0 ;
618
- BlockOrdinal NextBlockOrdinal = 0 ;
619
611
BlockSet Blocks;
620
612
SymbolSet Symbols;
621
613
};
@@ -815,15 +807,13 @@ class LinkGraph {
815
807
Block &createContentBlock (Section &Parent, StringRef Content,
816
808
uint64_t Address, uint64_t Alignment,
817
809
uint64_t AlignmentOffset) {
818
- return createBlock (Parent, Parent.getNextBlockOrdinal (), Content, Address,
819
- Alignment, AlignmentOffset);
810
+ return createBlock (Parent, Content, Address, Alignment, AlignmentOffset);
820
811
}
821
812
822
813
// / Create a zero-fill block.
823
814
Block &createZeroFillBlock (Section &Parent, uint64_t Size, uint64_t Address,
824
815
uint64_t Alignment, uint64_t AlignmentOffset) {
825
- return createBlock (Parent, Parent.getNextBlockOrdinal (), Size, Address,
826
- Alignment, AlignmentOffset);
816
+ return createBlock (Parent, Size, Address, Alignment, AlignmentOffset);
827
817
}
828
818
829
819
// / Cache type for the splitBlock function.
@@ -841,11 +831,18 @@ class LinkGraph {
841
831
// / is assumed to contain the list of Symbols pointing at B, sorted in
842
832
// / descending order of offset.
843
833
// /
844
- // / Note: The cache is not automatically updated if new symbols are introduced
845
- // / between calls to splitBlock. Any newly introduced symbols may be
846
- // / added to the cache manually (descending offset order must be
847
- // / preserved), or the cache can be set to None and rebuilt by
848
- // / splitBlock on the next call.
834
+ // / Notes:
835
+ // /
836
+ // / 1. The newly introduced block will have a new ordinal which will be
837
+ // / higher than any other ordinals in the section. Clients are responsible
838
+ // / for re-assigning block ordinals to restore a compatible order if
839
+ // / needed.
840
+ // /
841
+ // / 2. The cache is not automatically updated if new symbols are introduced
842
+ // / between calls to splitBlock. Any newly introduced symbols may be
843
+ // / added to the cache manually (descending offset order must be
844
+ // / preserved), or the cache can be set to None and rebuilt by
845
+ // / splitBlock on the next call.
849
846
Block &splitBlock (Block &B, size_t SplitIndex,
850
847
SplitBlockCache *Cache = nullptr );
851
848
@@ -875,9 +872,8 @@ class LinkGraph {
875
872
uint64_t Alignment, bool IsLive) {
876
873
auto &Sym = Symbol::constructCommon (
877
874
Allocator.Allocate <Symbol>(),
878
- createBlock (Section, Section.getNextBlockOrdinal (), Address, Size,
879
- Alignment, 0 ),
880
- Name, Size, S, IsLive);
875
+ createBlock (Section, Address, Size, Alignment, 0 ), Name, Size, S,
876
+ IsLive);
881
877
Section.addSymbol (Sym);
882
878
return Sym;
883
879
}
@@ -1019,6 +1015,145 @@ class LinkGraph {
1019
1015
ExternalSymbolSet AbsoluteSymbols;
1020
1016
};
1021
1017
1018
+ // / Enables easy lookup of blocks by addresses.
1019
+ class BlockAddressMap {
1020
+ public:
1021
+ using AddrToBlockMap = std::map<JITTargetAddress, Block *>;
1022
+ using const_iterator = AddrToBlockMap::const_iterator;
1023
+
1024
+ // / A block predicate that always adds all blocks.
1025
+ static bool includeAllBlocks (const Block &B) { return true ; }
1026
+
1027
+ // / A block predicate that always includes blocks with non-null addresses.
1028
+ static bool includeNonNull (const Block &B) { return B.getAddress (); }
1029
+
1030
+ BlockAddressMap () = default ;
1031
+
1032
+ // / Add a block to the map. Returns an error if the block overlaps with any
1033
+ // / existing block.
1034
+ template <typename PredFn = decltype (includeAllBlocks)>
1035
+ Error addBlock (Block &B, PredFn Pred = includeAllBlocks) {
1036
+ if (!Pred (B))
1037
+ return Error::success ();
1038
+
1039
+ auto I = AddrToBlock.upper_bound (B.getAddress ());
1040
+
1041
+ // If we're not at the end of the map, check for overlap with the next
1042
+ // element.
1043
+ if (I != AddrToBlock.end ()) {
1044
+ if (B.getAddress () + B.getSize () > I->second ->getAddress ())
1045
+ return overlapError (B, *I->second );
1046
+ }
1047
+
1048
+ // If we're not at the start of the map, check for overlap with the previous
1049
+ // element.
1050
+ if (I != AddrToBlock.begin ()) {
1051
+ auto &PrevBlock = *std::prev (I)->second ;
1052
+ if (PrevBlock.getAddress () + PrevBlock.getSize () > B.getAddress ())
1053
+ return overlapError (B, PrevBlock);
1054
+ }
1055
+
1056
+ AddrToBlock.insert (I, std::make_pair (B.getAddress (), &B));
1057
+ return Error::success ();
1058
+ }
1059
+
1060
+ // / Add a block to the map without checking for overlap with existing blocks.
1061
+ // / The client is responsible for ensuring that the block added does not
1062
+ // / overlap with any existing block.
1063
+ void addBlockWithoutChecking (Block &B) { AddrToBlock[B.getAddress ()] = &B; }
1064
+
1065
+ // / Add a range of blocks to the map. Returns an error if any block in the
1066
+ // / range overlaps with any other block in the range, or with any existing
1067
+ // / block in the map.
1068
+ template <typename BlockPtrRange,
1069
+ typename PredFn = decltype (includeAllBlocks)>
1070
+ Error addBlocks (BlockPtrRange &&Blocks, PredFn Pred = includeAllBlocks) {
1071
+ for (auto *B : Blocks)
1072
+ if (auto Err = addBlock (*B, Pred))
1073
+ return Err;
1074
+ return Error::success ();
1075
+ }
1076
+
1077
+ // / Add a range of blocks to the map without checking for overlap with
1078
+ // / existing blocks. The client is responsible for ensuring that the block
1079
+ // / added does not overlap with any existing block.
1080
+ template <typename BlockPtrRange>
1081
+ void addBlocksWithoutChecking (BlockPtrRange &&Blocks) {
1082
+ for (auto *B : Blocks)
1083
+ addBlockWithoutChecking (*B);
1084
+ }
1085
+
1086
+ // / Iterates over (Address, Block*) pairs in ascending order of address.
1087
+ const_iterator begin () const { return AddrToBlock.begin (); }
1088
+ const_iterator end () const { return AddrToBlock.end (); }
1089
+
1090
+ // / Returns the block starting at the given address, or nullptr if no such
1091
+ // / block exists.
1092
+ Block *getBlockAt (JITTargetAddress Addr) const {
1093
+ auto I = AddrToBlock.find (Addr);
1094
+ if (I == AddrToBlock.end ())
1095
+ return nullptr ;
1096
+ return I->second ;
1097
+ }
1098
+
1099
+ // / Returns the block covering the given address, or nullptr if no such block
1100
+ // / exists.
1101
+ Block *getBlockCovering (JITTargetAddress Addr) const {
1102
+ auto I = AddrToBlock.upper_bound (Addr);
1103
+ if (I == AddrToBlock.begin ())
1104
+ return nullptr ;
1105
+ auto *B = std::prev (I)->second ;
1106
+ if (Addr < B->getAddress () + B->getSize ())
1107
+ return B;
1108
+ return nullptr ;
1109
+ }
1110
+
1111
+ private:
1112
+ Error overlapError (Block &NewBlock, Block &ExistingBlock) {
1113
+ auto NewBlockEnd = NewBlock.getAddress () + NewBlock.getSize ();
1114
+ auto ExistingBlockEnd =
1115
+ ExistingBlock.getAddress () + ExistingBlock.getSize ();
1116
+ return make_error<JITLinkError>(
1117
+ " Block at " +
1118
+ formatv (" {0:x16} -- {1:x16}" , NewBlock.getAddress (), NewBlockEnd) +
1119
+ " overlaps " +
1120
+ formatv (" {0:x16} -- {1:x16}" , ExistingBlock.getAddress (),
1121
+ ExistingBlockEnd));
1122
+ }
1123
+
1124
+ AddrToBlockMap AddrToBlock;
1125
+ };
1126
+
1127
+ // / A map of addresses to Symbols.
1128
+ class SymbolAddressMap {
1129
+ public:
1130
+ using SymbolVector = SmallVector<Symbol *, 1 >;
1131
+
1132
+ // / Add a symbol to the SymbolAddressMap.
1133
+ void addSymbol (Symbol &Sym) {
1134
+ AddrToSymbols[Sym.getAddress ()].push_back (&Sym);
1135
+ }
1136
+
1137
+ // / Add all symbols in a given range to the SymbolAddressMap.
1138
+ template <typename SymbolPtrCollection>
1139
+ void addSymbols (SymbolPtrCollection &&Symbols) {
1140
+ for (auto *Sym : Symbols)
1141
+ addSymbol (*Sym);
1142
+ }
1143
+
1144
+ // / Returns the list of symbols that start at the given address, or nullptr if
1145
+ // / no such symbols exist.
1146
+ const SymbolVector *getSymbolsAt (JITTargetAddress Addr) const {
1147
+ auto I = AddrToSymbols.find (Addr);
1148
+ if (I == AddrToSymbols.end ())
1149
+ return nullptr ;
1150
+ return &I->second ;
1151
+ }
1152
+
1153
+ private:
1154
+ std::map<JITTargetAddress, SymbolVector> AddrToSymbols;
1155
+ };
1156
+
1022
1157
// / A function for mutating LinkGraphs.
1023
1158
using LinkGraphPassFunction = std::function<Error(LinkGraph &)>;
1024
1159
0 commit comments