mirror of
https://github.com/RPCSX/llvm.git
synced 2025-04-10 20:20:54 +00:00

Make sure strings don't get too big for a record, truncate them if need-be. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@273710 91177308-0d34-0410-b5e6-96231b3b80d8
103 lines
3.8 KiB
C++
103 lines
3.8 KiB
C++
//===-- ListRecordBuilder.cpp ---------------------------------------------===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "llvm/ADT/SmallString.h"
|
|
#include "llvm/DebugInfo/CodeView/ListRecordBuilder.h"
|
|
#include "llvm/DebugInfo/CodeView/TypeTableBuilder.h"
|
|
|
|
using namespace llvm;
|
|
using namespace codeview;
|
|
|
|
ListRecordBuilder::ListRecordBuilder(TypeRecordKind Kind)
|
|
: Kind(Kind), Builder(Kind) {}
|
|
|
|
void ListRecordBuilder::writeListContinuation(const ListContinuationRecord &R) {
|
|
TypeRecordBuilder &Builder = getBuilder();
|
|
|
|
assert(getLastContinuationSize() < 65535 - 8 && "continuation won't fit");
|
|
|
|
Builder.writeTypeRecordKind(TypeRecordKind::ListContinuation);
|
|
Builder.writeUInt16(0);
|
|
Builder.writeTypeIndex(R.getContinuationIndex());
|
|
|
|
// End the current segment manually so that nothing comes after the
|
|
// continuation.
|
|
ContinuationOffsets.push_back(Builder.size());
|
|
SubrecordStart = Builder.size();
|
|
}
|
|
|
|
void ListRecordBuilder::finishSubRecord() {
|
|
// The type table inserts a 16 bit size field before each list, so factor that
|
|
// into our alignment padding.
|
|
uint32_t Remainder =
|
|
(Builder.size() + 2 * (ContinuationOffsets.size() + 1)) % 4;
|
|
if (Remainder != 0) {
|
|
for (int32_t PaddingBytesLeft = 4 - Remainder; PaddingBytesLeft > 0;
|
|
--PaddingBytesLeft) {
|
|
Builder.writeUInt8(LF_PAD0 + PaddingBytesLeft);
|
|
}
|
|
}
|
|
|
|
// Check if this subrecord makes the current segment not fit in 64K minus the
|
|
// space for a continuation record (8 bytes). If the segment does not fit,
|
|
// back up and insert a continuation record, sliding the current subrecord
|
|
// down.
|
|
if (getLastContinuationSize() > 65535 - 8) {
|
|
assert(SubrecordStart != 0 && "can't slide from the start!");
|
|
SmallString<128> SubrecordCopy(
|
|
Builder.str().slice(SubrecordStart, Builder.size()));
|
|
assert(SubrecordCopy.size() < 65530 && "subrecord is too large to slide!");
|
|
Builder.truncate(SubrecordStart);
|
|
|
|
// Write a placeholder continuation record.
|
|
Builder.writeTypeRecordKind(TypeRecordKind::ListContinuation);
|
|
Builder.writeUInt16(0);
|
|
Builder.writeUInt32(0);
|
|
ContinuationOffsets.push_back(Builder.size());
|
|
assert(Builder.size() == SubrecordStart + 8 && "wrong continuation size");
|
|
assert(getLastContinuationSize() < 65535 && "segment too big");
|
|
|
|
// Start a new list record of the appropriate kind, and copy the previous
|
|
// subrecord into place.
|
|
Builder.writeTypeRecordKind(Kind);
|
|
Builder.writeBytes(SubrecordCopy);
|
|
}
|
|
|
|
SubrecordStart = Builder.size();
|
|
}
|
|
|
|
TypeIndex ListRecordBuilder::writeListRecord(TypeTableBuilder &Table) {
|
|
// Get the continuation segments as a reversed vector of StringRefs for
|
|
// convenience.
|
|
SmallVector<StringRef, 1> Segments;
|
|
StringRef Data = str();
|
|
size_t LastEnd = 0;
|
|
for (size_t SegEnd : ContinuationOffsets) {
|
|
Segments.push_back(Data.slice(LastEnd, SegEnd));
|
|
LastEnd = SegEnd;
|
|
}
|
|
Segments.push_back(Data.slice(LastEnd, Builder.size()));
|
|
|
|
// Pop the last record off and emit it directly.
|
|
StringRef LastRec = Segments.pop_back_val();
|
|
TypeIndex ContinuationIndex = Table.writeRecord(LastRec);
|
|
|
|
// Emit each record with a continuation in reverse order, so that each one
|
|
// references the previous record.
|
|
for (StringRef Rec : reverse(Segments)) {
|
|
assert(*reinterpret_cast<const ulittle16_t *>(Rec.data()) ==
|
|
unsigned(Kind));
|
|
ulittle32_t *ContinuationPtr =
|
|
reinterpret_cast<ulittle32_t *>(const_cast<char *>(Rec.end())) - 1;
|
|
*ContinuationPtr = ContinuationIndex.getIndex();
|
|
ContinuationIndex = Table.writeRecord(Rec);
|
|
}
|
|
return ContinuationIndex;
|
|
}
|