return orc::ExecutorAddr(alignToBlock(Addr.getValue(), B));
}
+// Returns true if the given blocks contains exactly one valid c-string.
+// Zero-fill blocks of size 1 count as valid empty strings. Content blocks
+// must end with a zero, and contain no zeros before the end.
+bool isCStringBlock(Block &B);
+
/// Describes symbol linkage. This can be used to make resolve definition
/// clashes.
enum class Linkage : uint8_t {
llvm_unreachable("Unrecognized llvm.jitlink.Scope enum");
}
+bool isCStringBlock(Block &B) {
+ if (B.getSize() == 0) // Empty blocks are not valid C-strings.
+ return false;
+
+ // Zero-fill blocks of size one are valid empty strings.
+ if (B.isZeroFill())
+ return B.getSize() == 1;
+
+ for (size_t I = 0; I != B.getSize() - 1; ++I)
+ if (B.getContent()[I] == '\0')
+ return false;
+
+ return B.getContent()[B.getSize() - 1] == '\0';
+}
+
raw_ostream &operator<<(raw_ostream &OS, const Block &B) {
return OS << B.getAddress() << " -- " << (B.getAddress() + B.getSize())
<< ": "
orc::ExecutorAddrDiff BlockStart = 0;
// Scan section for null characters.
- for (size_t I = 0; I != NSec.Size; ++I)
+ for (size_t I = 0; I != NSec.Size; ++I) {
if (NSec.Data[I] == '\0') {
size_t BlockSize = I + 1 - BlockStart;
// Create a block for this null terminated string.
BlockStart += BlockSize;
}
+ }
+
+ assert(llvm::all_of(NSec.GraphSection->blocks(),
+ [](Block *B) { return isCStringBlock(*B); }) &&
+ "All blocks in section should hold single c-strings");
return Error::success();
}
EXPECT_EQ(E2->getOffset(), 4U);
}
}
+
+TEST(LinkGraphTest, IsCStringBlockTest) {
+ // Check that the LinkGraph::splitBlock test works as expected.
+ LinkGraph G("foo", Triple("x86_64-apple-darwin"), 8, support::little,
+ getGenericEdgeKindName);
+ auto &Sec =
+ G.createSection("__data", orc::MemProt::Read | orc::MemProt::Write);
+
+ ArrayRef<char> CString = "hello, world!";
+ ArrayRef<char> NotACString = {0, 1, 0, 1, 0};
+
+ auto &CStringBlock =
+ G.createContentBlock(Sec, CString, orc::ExecutorAddr(), 1, 0);
+ auto &NotACStringBlock =
+ G.createContentBlock(Sec, NotACString, orc::ExecutorAddr(), 1, 0);
+ auto &SizeOneZeroFillBlock =
+ G.createZeroFillBlock(Sec, 1, orc::ExecutorAddr(), 1, 0);
+ auto &LargerZeroFillBlock =
+ G.createZeroFillBlock(Sec, 2, orc::ExecutorAddr(), 1, 0);
+
+ EXPECT_TRUE(isCStringBlock(CStringBlock));
+ EXPECT_FALSE(isCStringBlock(NotACStringBlock));
+ EXPECT_TRUE(isCStringBlock(SizeOneZeroFillBlock));
+ EXPECT_FALSE(isCStringBlock(LargerZeroFillBlock));
+}