[codeview] Truncate records to maximum record size near 64KB

If we don't truncate, LLVM asserts when the label difference doesn't fit
in a 16 bit field. This patch truncates two kinds of data: trailing null
terminated names in symbol records, and inline line tables. The inline
line table test that I have is too large (many MB), so I'm not checking
it in.

Hopefully fixes PR28264.

llvm-svn: 283403
This commit is contained in:
Reid Kleckner 2016-10-05 22:36:07 +00:00
parent 5aa0248059
commit bb96df602e
3 changed files with 57 additions and 4 deletions

View File

@ -432,10 +432,13 @@ void CodeViewDebug::endModule() {
} }
static void emitNullTerminatedSymbolName(MCStreamer &OS, StringRef S) { static void emitNullTerminatedSymbolName(MCStreamer &OS, StringRef S) {
// Microsoft's linker seems to have trouble with symbol names longer than // The maximum CV record length is 0xFF00. Most of the strings we emit appear
// 0xffd8 bytes. // after a fixed length portion of the record. The fixed length portion should
S = S.substr(0, 0xffd8); // always be less than 0xF00 (3840) bytes, so truncate the string so that the
SmallString<32> NullTerminatedString(S); // overall record size is less than the maximum allowed.
unsigned MaxFixedRecordLength = 0xF00;
SmallString<32> NullTerminatedString(
S.take_front(MaxRecordLength - MaxFixedRecordLength - 1));
NullTerminatedString.push_back('\0'); NullTerminatedString.push_back('\0');
OS.EmitBytes(NullTerminatedString); OS.EmitBytes(NullTerminatedString);
} }

View File

@ -358,6 +358,13 @@ void CodeViewContext::encodeInlineLineTable(MCAsmLayout &Layout,
SmallVectorImpl<char> &Buffer = Frag.getContents(); SmallVectorImpl<char> &Buffer = Frag.getContents();
Buffer.clear(); // Clear old contents if we went through relaxation. Buffer.clear(); // Clear old contents if we went through relaxation.
for (const MCCVLineEntry &Loc : Locs) { for (const MCCVLineEntry &Loc : Locs) {
// Exit early if our line table would produce an oversized InlineSiteSym
// record. Account for the ChangeCodeLength annotation emitted after the
// loop ends.
size_t MaxBufferSize = MaxRecordLength - sizeof(InlineSiteSym::Hdr) - 8;
if (Buffer.size() >= MaxBufferSize)
break;
if (Loc.getFunctionId() == Frag.SiteFuncId) { if (Loc.getFunctionId() == Frag.SiteFuncId) {
CurSourceLoc.File = Loc.getFileNum(); CurSourceLoc.File = Loc.getFileNum();
CurSourceLoc.Line = Loc.getLine(); CurSourceLoc.Line = Loc.getLine();

File diff suppressed because one or more lines are too long