|
@@ -7,6 +7,7 @@
|
|
//===----------------------------------------------------------------------===//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
#include "llvm/ObjectYAML/MinidumpYAML.h"
|
|
#include "llvm/ObjectYAML/MinidumpYAML.h"
|
|
|
|
+#include "llvm/Support/ConvertUTF.h"
|
|
|
|
|
|
using namespace llvm;
|
|
using namespace llvm;
|
|
using namespace llvm::MinidumpYAML;
|
|
using namespace llvm::MinidumpYAML;
|
|
@@ -39,6 +40,8 @@ public:
|
|
return allocateArray(makeArrayRef(Data));
|
|
return allocateArray(makeArrayRef(Data));
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ size_t allocateString(StringRef Str);
|
|
|
|
+
|
|
void writeTo(raw_ostream &OS) const;
|
|
void writeTo(raw_ostream &OS) const;
|
|
|
|
|
|
private:
|
|
private:
|
|
@@ -48,6 +51,26 @@ private:
|
|
};
|
|
};
|
|
} // namespace
|
|
} // namespace
|
|
|
|
|
|
|
|
+size_t BlobAllocator::allocateString(StringRef Str) {
|
|
|
|
+ SmallVector<UTF16, 32> WStr;
|
|
|
|
+ bool OK = convertUTF8ToUTF16String(Str, WStr);
|
|
|
|
+ assert(OK && "Invalid UTF8 in Str?");
|
|
|
|
+ (void)OK;
|
|
|
|
+
|
|
|
|
+ SmallVector<support::ulittle16_t, 32> EndianStr(WStr.size() + 1,
|
|
|
|
+ support::ulittle16_t());
|
|
|
|
+ copy(WStr, EndianStr.begin());
|
|
|
|
+ return allocateCallback(
|
|
|
|
+ sizeof(uint32_t) + EndianStr.size() * sizeof(support::ulittle16_t),
|
|
|
|
+ [EndianStr](raw_ostream &OS) {
|
|
|
|
+ // Length does not include the null-terminator.
|
|
|
|
+ support::ulittle32_t Length(2 * (EndianStr.size() - 1));
|
|
|
|
+ OS.write(reinterpret_cast<const char *>(&Length), sizeof(Length));
|
|
|
|
+ OS.write(reinterpret_cast<const char *>(EndianStr.begin()),
|
|
|
|
+ sizeof(support::ulittle16_t) * EndianStr.size());
|
|
|
|
+ });
|
|
|
|
+}
|
|
|
|
+
|
|
void BlobAllocator::writeTo(raw_ostream &OS) const {
|
|
void BlobAllocator::writeTo(raw_ostream &OS) const {
|
|
size_t BeginOffset = OS.tell();
|
|
size_t BeginOffset = OS.tell();
|
|
for (const auto &Callback : Callbacks)
|
|
for (const auto &Callback : Callbacks)
|
|
@@ -269,7 +292,7 @@ static void streamMapping(yaml::IO &IO, SystemInfoStream &Stream) {
|
|
mapOptional(IO, "Minor Version", Info.MinorVersion, 0);
|
|
mapOptional(IO, "Minor Version", Info.MinorVersion, 0);
|
|
mapOptional(IO, "Build Number", Info.BuildNumber, 0);
|
|
mapOptional(IO, "Build Number", Info.BuildNumber, 0);
|
|
IO.mapRequired("Platform ID", Info.PlatformId);
|
|
IO.mapRequired("Platform ID", Info.PlatformId);
|
|
- mapOptionalHex(IO, "CSD Version RVA", Info.CSDVersionRVA, 0);
|
|
|
|
|
|
+ IO.mapOptional("CSD Version", Stream.CSDVersion, "");
|
|
mapOptionalHex(IO, "Suite Mask", Info.SuiteMask, 0);
|
|
mapOptionalHex(IO, "Suite Mask", Info.SuiteMask, 0);
|
|
mapOptionalHex(IO, "Reserved", Info.Reserved, 0);
|
|
mapOptionalHex(IO, "Reserved", Info.Reserved, 0);
|
|
switch (static_cast<ProcessorArchitecture>(Info.ProcessorArch)) {
|
|
switch (static_cast<ProcessorArchitecture>(Info.ProcessorArch)) {
|
|
@@ -337,6 +360,7 @@ static Directory layout(BlobAllocator &File, Stream &S) {
|
|
Directory Result;
|
|
Directory Result;
|
|
Result.Type = S.Type;
|
|
Result.Type = S.Type;
|
|
Result.Location.RVA = File.tell();
|
|
Result.Location.RVA = File.tell();
|
|
|
|
+ Optional<size_t> DataEnd;
|
|
switch (S.Kind) {
|
|
switch (S.Kind) {
|
|
case Stream::StreamKind::RawContent: {
|
|
case Stream::StreamKind::RawContent: {
|
|
RawContentStream &Raw = cast<RawContentStream>(S);
|
|
RawContentStream &Raw = cast<RawContentStream>(S);
|
|
@@ -347,14 +371,22 @@ static Directory layout(BlobAllocator &File, Stream &S) {
|
|
});
|
|
});
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
- case Stream::StreamKind::SystemInfo:
|
|
|
|
- File.allocateObject(cast<SystemInfoStream>(S).Info);
|
|
|
|
|
|
+ case Stream::StreamKind::SystemInfo: {
|
|
|
|
+ SystemInfoStream &SystemInfo = cast<SystemInfoStream>(S);
|
|
|
|
+ File.allocateObject(SystemInfo.Info);
|
|
|
|
+ // The CSD string is not a part of the stream.
|
|
|
|
+ DataEnd = File.tell();
|
|
|
|
+ SystemInfo.Info.CSDVersionRVA = File.allocateString(SystemInfo.CSDVersion);
|
|
break;
|
|
break;
|
|
|
|
+ }
|
|
case Stream::StreamKind::TextContent:
|
|
case Stream::StreamKind::TextContent:
|
|
File.allocateArray(arrayRefFromStringRef(cast<TextContentStream>(S).Text));
|
|
File.allocateArray(arrayRefFromStringRef(cast<TextContentStream>(S).Text));
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
- Result.Location.DataSize = File.tell() - Result.Location.RVA;
|
|
|
|
|
|
+ // If DataEnd is not set, we assume everything we generated is a part of the
|
|
|
|
+ // stream.
|
|
|
|
+ Result.Location.DataSize =
|
|
|
|
+ DataEnd.getValueOr(File.tell()) - Result.Location.RVA;
|
|
return Result;
|
|
return Result;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -395,7 +427,11 @@ Stream::create(const Directory &StreamDesc, const object::MinidumpFile &File) {
|
|
auto ExpectedInfo = File.getSystemInfo();
|
|
auto ExpectedInfo = File.getSystemInfo();
|
|
if (!ExpectedInfo)
|
|
if (!ExpectedInfo)
|
|
return ExpectedInfo.takeError();
|
|
return ExpectedInfo.takeError();
|
|
- return make_unique<SystemInfoStream>(*ExpectedInfo);
|
|
|
|
|
|
+ auto ExpectedCSDVersion = File.getString(ExpectedInfo->CSDVersionRVA);
|
|
|
|
+ if (!ExpectedCSDVersion)
|
|
|
|
+ return ExpectedInfo.takeError();
|
|
|
|
+ return make_unique<SystemInfoStream>(*ExpectedInfo,
|
|
|
|
+ std::move(*ExpectedCSDVersion));
|
|
}
|
|
}
|
|
case StreamKind::TextContent:
|
|
case StreamKind::TextContent:
|
|
return make_unique<TextContentStream>(
|
|
return make_unique<TextContentStream>(
|