cb424d7448
verify-patch-sanity.py validates every active recipe .patch has internally- consistent hunk line counts — catching the 'malformed patch at line N' failure at commit/CI/preflight time instead of hours into a cook. This cycle hit that class three times (qtwaylandscanner, sddm, xwayland), each only discovered when cookbook tried to apply the patch. Running it across the repo found 29 latent malformed patches (validated against GNU patch: e.g. relibc/P3-sysv-ipc reproduces 'malformed patch at line 22'). They were harmless only because they sit in vendored recipes (baked, not re- applied) — but would fail on any version-bump re-derivation. --fix recounts the hunk headers (body untouched) and repaired all 29. Wired into build-preflight.sh (Phase 1.0D) and redbear-ci.yml, with a unit test (test-patch-sanity.sh). Skips archived/legacy trees and unvalidatable formats (empty placeholders, bare-@@ git hunks).
602 lines
22 KiB
C++
602 lines
22 KiB
C++
//===- GOFFObjectFileTest.cpp - Tests for GOFFObjectFile ------------------===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "llvm/Object/GOFFObjectFile.h"
|
|
#include "llvm/Support/MemoryBuffer.h"
|
|
#include "llvm/Testing/Support/Error.h"
|
|
#include "gtest/gtest.h"
|
|
|
|
using namespace llvm;
|
|
using namespace llvm::object;
|
|
using namespace llvm::GOFF;
|
|
|
|
namespace {
|
|
char GOFFData[GOFF::RecordLength * 3] = {0x00};
|
|
|
|
void constructValidGOFF(size_t Size) {
|
|
StringRef ValidSize(GOFFData, Size);
|
|
Expected<std::unique_ptr<ObjectFile>> GOFFObjOrErr =
|
|
object::ObjectFile::createGOFFObjectFile(
|
|
MemoryBufferRef(ValidSize, "dummyGOFF"));
|
|
|
|
ASSERT_THAT_EXPECTED(GOFFObjOrErr, Succeeded());
|
|
}
|
|
|
|
void constructInvalidGOFF(size_t Size) {
|
|
// Construct GOFFObject with record of length != multiple of 80.
|
|
StringRef InvalidData(GOFFData, Size);
|
|
Expected<std::unique_ptr<ObjectFile>> GOFFObjOrErr =
|
|
object::ObjectFile::createGOFFObjectFile(
|
|
MemoryBufferRef(InvalidData, "dummyGOFF"));
|
|
|
|
ASSERT_THAT_EXPECTED(
|
|
GOFFObjOrErr,
|
|
FailedWithMessage("object file is not the right size. Must be a multiple "
|
|
"of 80 bytes, but is " +
|
|
std::to_string(Size) + " bytes"));
|
|
}
|
|
} // namespace
|
|
|
|
TEST(GOFFObjectFileTest, ConstructGOFFObjectValidSize) {
|
|
GOFFData[0] = (char)0x03;
|
|
GOFFData[1] = (char)0xF0;
|
|
GOFFData[80] = (char)0x03;
|
|
GOFFData[81] = (char)0x40;
|
|
constructValidGOFF(160);
|
|
constructValidGOFF(0);
|
|
}
|
|
|
|
TEST(GOFFObjectFileTest, ConstructGOFFObjectInvalidSize) {
|
|
constructInvalidGOFF(70);
|
|
constructInvalidGOFF(79);
|
|
constructInvalidGOFF(81);
|
|
}
|
|
|
|
TEST(GOFFObjectFileTest, MissingHDR) {
|
|
char GOFFData[GOFF::RecordLength * 2] = {0x00};
|
|
|
|
// ESD record.
|
|
GOFFData[0] = (char)0x03;
|
|
|
|
// END record.
|
|
GOFFData[GOFF::RecordLength] = (char)0x03;
|
|
GOFFData[GOFF::RecordLength + 1] = (char)0x40;
|
|
|
|
StringRef Data(GOFFData, GOFF::RecordLength * 2);
|
|
|
|
Expected<std::unique_ptr<ObjectFile>> GOFFObjOrErr =
|
|
object::ObjectFile::createGOFFObjectFile(
|
|
MemoryBufferRef(Data, "dummyGOFF"));
|
|
|
|
ASSERT_THAT_EXPECTED(
|
|
GOFFObjOrErr,
|
|
FailedWithMessage("object file must start with HDR record"));
|
|
}
|
|
|
|
TEST(GOFFObjectFileTest, MissingEND) {
|
|
char GOFFData[GOFF::RecordLength * 2] = {0x00};
|
|
|
|
// HDR record.
|
|
GOFFData[0] = (char)0x03;
|
|
GOFFData[1] = (char)0xF0;
|
|
|
|
// ESD record.
|
|
GOFFData[GOFF::RecordLength] = (char)0x03;
|
|
|
|
StringRef Data(GOFFData, GOFF::RecordLength * 2);
|
|
|
|
Expected<std::unique_ptr<ObjectFile>> GOFFObjOrErr =
|
|
object::ObjectFile::createGOFFObjectFile(
|
|
MemoryBufferRef(Data, "dummyGOFF"));
|
|
|
|
ASSERT_THAT_EXPECTED(
|
|
GOFFObjOrErr, FailedWithMessage("object file must end with END record"));
|
|
}
|
|
|
|
TEST(GOFFObjectFileTest, GetSymbolName) {
|
|
char GOFFData[GOFF::RecordLength * 3] = {0x00};
|
|
|
|
// HDR record.
|
|
GOFFData[0] = (char)0x03;
|
|
GOFFData[1] = (char)0xF0;
|
|
|
|
// ESD record.
|
|
GOFFData[GOFF::RecordLength] = (char)0x03;
|
|
GOFFData[GOFF::RecordLength + 3] = (char)0x02;
|
|
GOFFData[GOFF::RecordLength + 7] = (char)0x01;
|
|
GOFFData[GOFF::RecordLength + 11] = (char)0x01;
|
|
GOFFData[GOFF::RecordLength + 71] = (char)0x05; // Size of symbol name.
|
|
GOFFData[GOFF::RecordLength + 72] = (char)0xC8; // Symbol name is Hello.
|
|
GOFFData[GOFF::RecordLength + 73] = (char)0x85;
|
|
GOFFData[GOFF::RecordLength + 74] = (char)0x93;
|
|
GOFFData[GOFF::RecordLength + 75] = (char)0x93;
|
|
GOFFData[GOFF::RecordLength + 76] = (char)0x96;
|
|
|
|
// END record.
|
|
GOFFData[GOFF::RecordLength * 2] = 0x03;
|
|
GOFFData[GOFF::RecordLength * 2 + 1] = 0x40;
|
|
|
|
StringRef Data(GOFFData, GOFF::RecordLength * 3);
|
|
|
|
Expected<std::unique_ptr<ObjectFile>> GOFFObjOrErr =
|
|
object::ObjectFile::createGOFFObjectFile(
|
|
MemoryBufferRef(Data, "dummyGOFF"));
|
|
|
|
ASSERT_THAT_EXPECTED(GOFFObjOrErr, Succeeded());
|
|
|
|
GOFFObjectFile *GOFFObj = dyn_cast<GOFFObjectFile>((*GOFFObjOrErr).get());
|
|
|
|
for (SymbolRef Symbol : GOFFObj->symbols()) {
|
|
Expected<StringRef> SymbolNameOrErr = GOFFObj->getSymbolName(Symbol);
|
|
ASSERT_THAT_EXPECTED(SymbolNameOrErr, Succeeded());
|
|
StringRef SymbolName = SymbolNameOrErr.get();
|
|
|
|
EXPECT_EQ(SymbolName, "Hello");
|
|
}
|
|
}
|
|
|
|
TEST(GOFFObjectFileTest, ConcatenatedGOFFFile) {
|
|
char GOFFData[GOFF::RecordLength * 6] = {0x00};
|
|
|
|
// HDR record.
|
|
GOFFData[0] = (char)0x03;
|
|
GOFFData[1] = (char)0xF0;
|
|
// ESD record.
|
|
GOFFData[GOFF::RecordLength] = (char)0x03;
|
|
// END record.
|
|
GOFFData[GOFF::RecordLength * 2] = (char)0x03;
|
|
GOFFData[GOFF::RecordLength * 2 + 1] = (char)0x40;
|
|
// HDR record.
|
|
GOFFData[GOFF::RecordLength * 3] = (char)0x03;
|
|
GOFFData[GOFF::RecordLength * 3 + 1] = (char)0xF0;
|
|
// ESD record.
|
|
GOFFData[GOFF::RecordLength * 4] = (char)0x03;
|
|
// END record.
|
|
GOFFData[GOFF::RecordLength * 5] = (char)0x03;
|
|
GOFFData[GOFF::RecordLength * 5 + 1] = (char)0x40;
|
|
|
|
StringRef Data(GOFFData, GOFF::RecordLength * 6);
|
|
|
|
Expected<std::unique_ptr<ObjectFile>> GOFFObjOrErr =
|
|
object::ObjectFile::createGOFFObjectFile(
|
|
MemoryBufferRef(Data, "dummyGOFF"));
|
|
|
|
ASSERT_THAT_EXPECTED(GOFFObjOrErr, Succeeded());
|
|
}
|
|
|
|
TEST(GOFFObjectFileTest, ContinuationGetSymbolName) {
|
|
char GOFFContData[GOFF::RecordLength * 4] = {0x00};
|
|
|
|
// HDR record.
|
|
GOFFContData[0] = (char)0x03;
|
|
GOFFContData[1] = (char)0xF0;
|
|
|
|
// ESD record.
|
|
GOFFContData[GOFF::RecordLength] = (char)0x03;
|
|
GOFFContData[GOFF::RecordLength + 1] = (char)0x01;
|
|
GOFFContData[GOFF::RecordLength + 3] = (char)0x02;
|
|
GOFFContData[GOFF::RecordLength + 7] = (char)0x01;
|
|
GOFFContData[GOFF::RecordLength + 11] = (char)0x01;
|
|
GOFFContData[GOFF::RecordLength + 71] = (char)0x0A; // Size of symbol name.
|
|
GOFFContData[GOFF::RecordLength + 72] = (char)0xC8; // Symbol name is HelloWorld.
|
|
GOFFContData[GOFF::RecordLength + 73] = (char)0x85;
|
|
GOFFContData[GOFF::RecordLength + 74] = (char)0x93;
|
|
GOFFContData[GOFF::RecordLength + 75] = (char)0x93;
|
|
GOFFContData[GOFF::RecordLength + 76] = (char)0x96;
|
|
GOFFContData[GOFF::RecordLength + 77] = (char)0xA6;
|
|
GOFFContData[GOFF::RecordLength + 78] = (char)0x96;
|
|
GOFFContData[GOFF::RecordLength + 79] = (char)0x99;
|
|
|
|
// ESD continuation record.
|
|
GOFFContData[GOFF::RecordLength * 2] = (char)0x03;
|
|
GOFFContData[GOFF::RecordLength * 2 + 1] = (char)0x02; // No further continuations.
|
|
GOFFContData[GOFF::RecordLength * 2 + 3] = (char)0x93;
|
|
GOFFContData[GOFF::RecordLength * 2 + 4] = (char)0x84;
|
|
|
|
// END record.
|
|
GOFFContData[GOFF::RecordLength * 3] = (char)0x03;
|
|
GOFFContData[GOFF::RecordLength * 3 + 1] = (char)0x40;
|
|
|
|
StringRef Data(GOFFContData, GOFF::RecordLength * 4);
|
|
|
|
Expected<std::unique_ptr<ObjectFile>> GOFFObjOrErr =
|
|
object::ObjectFile::createGOFFObjectFile(
|
|
MemoryBufferRef(Data, "dummyGOFF"));
|
|
|
|
ASSERT_THAT_EXPECTED(GOFFObjOrErr, Succeeded());
|
|
|
|
GOFFObjectFile *GOFFObj = dyn_cast<GOFFObjectFile>((*GOFFObjOrErr).get());
|
|
|
|
for (SymbolRef Symbol : GOFFObj->symbols()) {
|
|
Expected<StringRef> SymbolNameOrErr = GOFFObj->getSymbolName(Symbol);
|
|
ASSERT_THAT_EXPECTED(SymbolNameOrErr, Succeeded());
|
|
StringRef SymbolName = SymbolNameOrErr.get();
|
|
EXPECT_EQ(SymbolName, "Helloworld");
|
|
}
|
|
}
|
|
|
|
TEST(GOFFObjectFileTest, ContinuationBitNotSet) {
|
|
char GOFFContData[GOFF::RecordLength * 4] = {0x00};
|
|
|
|
// HDR record.
|
|
GOFFContData[0] = (char)0x03;
|
|
GOFFContData[1] = (char)0xF0;
|
|
|
|
// ESD record.
|
|
GOFFContData[GOFF::RecordLength] = (char)0x03;
|
|
GOFFContData[GOFF::RecordLength + 1] = (char)0x01;
|
|
GOFFContData[GOFF::RecordLength + 3] = (char)0x02;
|
|
GOFFContData[GOFF::RecordLength + 7] = (char)0x01;
|
|
GOFFContData[GOFF::RecordLength + 11] = (char)0x01;
|
|
GOFFContData[GOFF::RecordLength + 71] = (char)0x0A; // Size of symbol name.
|
|
GOFFContData[GOFF::RecordLength + 72] = (char)0xC8; // Symbol name is HelloWorld.
|
|
GOFFContData[GOFF::RecordLength + 73] = (char)0x85;
|
|
GOFFContData[GOFF::RecordLength + 74] = (char)0x93;
|
|
GOFFContData[GOFF::RecordLength + 75] = (char)0x93;
|
|
GOFFContData[GOFF::RecordLength + 76] = (char)0x96;
|
|
GOFFContData[GOFF::RecordLength + 77] = (char)0xA6;
|
|
GOFFContData[GOFF::RecordLength + 78] = (char)0x96;
|
|
GOFFContData[GOFF::RecordLength + 79] = (char)0x99;
|
|
|
|
// ESD continuation record.
|
|
GOFFContData[GOFF::RecordLength * 2] = (char)0x03;
|
|
GOFFContData[GOFF::RecordLength * 2 + 1] = (char)0x00;
|
|
GOFFContData[GOFF::RecordLength * 2 + 3] = (char)0x93;
|
|
GOFFContData[GOFF::RecordLength * 2 + 4] = (char)0x84;
|
|
|
|
// END record.
|
|
GOFFContData[GOFF::RecordLength * 3] = (char)0x03;
|
|
GOFFContData[GOFF::RecordLength * 3 + 1] = (char)0x40;
|
|
|
|
StringRef Data(GOFFContData, GOFF::RecordLength * 4);
|
|
|
|
Expected<std::unique_ptr<ObjectFile>> GOFFObjOrErr =
|
|
object::ObjectFile::createGOFFObjectFile(
|
|
MemoryBufferRef(Data, "dummyGOFF"));
|
|
EXPECT_THAT_EXPECTED(
|
|
GOFFObjOrErr,
|
|
FailedWithMessage("record 2 is not a continuation record but the "
|
|
"preceding record is continued"));
|
|
}
|
|
|
|
TEST(GOFFObjectFileTest, ContinuationRecordNotTerminated) {
|
|
char GOFFContData[GOFF::RecordLength * 4] = {0x00};
|
|
|
|
// HDR record.
|
|
GOFFContData[0] = (char)0x03;
|
|
GOFFContData[1] = (char)0xF0;
|
|
|
|
// ESD record.
|
|
GOFFContData[GOFF::RecordLength] = (char)0x03;
|
|
GOFFContData[GOFF::RecordLength + 1] = (char)0x01;
|
|
GOFFContData[GOFF::RecordLength + 3] = (char)0x02;
|
|
GOFFContData[GOFF::RecordLength + 7] = (char)0x01;
|
|
GOFFContData[GOFF::RecordLength + 11] = (char)0x01;
|
|
GOFFContData[GOFF::RecordLength + 71] = (char)0x0A; // Size of symbol name.
|
|
GOFFContData[GOFF::RecordLength + 72] = (char)0xC8; // Symbol name is HelloWorld.
|
|
GOFFContData[GOFF::RecordLength + 73] = (char)0x85;
|
|
GOFFContData[GOFF::RecordLength + 74] = (char)0x93;
|
|
GOFFContData[GOFF::RecordLength + 75] = (char)0x93;
|
|
GOFFContData[GOFF::RecordLength + 76] = (char)0x96;
|
|
GOFFContData[GOFF::RecordLength + 77] = (char)0xA6;
|
|
GOFFContData[GOFF::RecordLength + 78] = (char)0x96;
|
|
GOFFContData[GOFF::RecordLength + 79] = (char)0x99;
|
|
|
|
// ESD continuation record.
|
|
GOFFContData[GOFF::RecordLength * 2] = (char)0x03;
|
|
GOFFContData[GOFF::RecordLength * 2 + 1] = (char)0x03; // Continued bit set.
|
|
GOFFContData[GOFF::RecordLength * 2 + 3] = (char)0x93;
|
|
GOFFContData[GOFF::RecordLength * 2 + 4] = (char)0x84;
|
|
|
|
// END record.
|
|
GOFFContData[GOFF::RecordLength * 3] = (char)0x03;
|
|
GOFFContData[GOFF::RecordLength * 3 + 1] = (char)0x40;
|
|
|
|
StringRef Data(GOFFContData, GOFF::RecordLength * 4);
|
|
|
|
Expected<std::unique_ptr<ObjectFile>> GOFFObjOrErr =
|
|
object::ObjectFile::createGOFFObjectFile(
|
|
MemoryBufferRef(Data, "dummyGOFF"));
|
|
ASSERT_THAT_EXPECTED(GOFFObjOrErr, Succeeded());
|
|
|
|
GOFFObjectFile *GOFFObj = dyn_cast<GOFFObjectFile>((*GOFFObjOrErr).get());
|
|
|
|
for (SymbolRef Symbol : GOFFObj->symbols()) {
|
|
Expected<StringRef> SymbolNameOrErr = GOFFObj->getSymbolName(Symbol);
|
|
EXPECT_THAT_EXPECTED(SymbolNameOrErr,
|
|
FailedWithMessage("continued bit should not be set"));
|
|
}
|
|
}
|
|
|
|
TEST(GOFFObjectFileTest, PrevNotContinued) {
|
|
char GOFFContData[GOFF::RecordLength * 4] = {0x00};
|
|
|
|
// HDR record.
|
|
GOFFContData[0] = (char)0x03;
|
|
GOFFContData[1] = (char)0xF0;
|
|
|
|
// ESD record, with continued bit not set.
|
|
GOFFContData[GOFF::RecordLength] = (char)0x03;
|
|
|
|
// ESD continuation record.
|
|
GOFFContData[GOFF::RecordLength * 2] = (char)0x03;
|
|
GOFFContData[GOFF::RecordLength * 2 + 1] = (char)0x02;
|
|
|
|
// END record.
|
|
GOFFContData[GOFF::RecordLength * 3] = (char)0x03;
|
|
GOFFContData[GOFF::RecordLength * 3 + 1] = (char)0x40;
|
|
|
|
StringRef Data(GOFFContData, GOFF::RecordLength * 4);
|
|
|
|
Expected<std::unique_ptr<ObjectFile>> GOFFObjOrErr =
|
|
object::ObjectFile::createGOFFObjectFile(
|
|
MemoryBufferRef(Data, "dummyGOFF"));
|
|
|
|
ASSERT_THAT_EXPECTED(
|
|
GOFFObjOrErr,
|
|
FailedWithMessage("record 2 is a continuation record that is not "
|
|
"preceded by a continued record"));
|
|
}
|
|
|
|
TEST(GOFFObjectFileTest, ContinuationTypeMismatch) {
|
|
char GOFFContData[GOFF::RecordLength * 4] = {0x00};
|
|
|
|
// HDR record.
|
|
GOFFContData[0] = (char)0x03;
|
|
GOFFContData[1] = (char)0xF0;
|
|
|
|
// ESD record.
|
|
GOFFContData[GOFF::RecordLength] = (char)0x03;
|
|
GOFFContData[GOFF::RecordLength + 1] = (char)0x01; // Continued to next record.
|
|
|
|
// END continuation record.
|
|
GOFFContData[GOFF::RecordLength * 2] = (char)0x03;
|
|
GOFFContData[GOFF::RecordLength * 2 + 1] = (char)0x42;
|
|
|
|
// END record.
|
|
GOFFContData[GOFF::RecordLength * 3] = (char)0x03;
|
|
GOFFContData[GOFF::RecordLength * 3 + 1] = (char)0x40;
|
|
|
|
StringRef Data(GOFFContData, GOFF::RecordLength * 4);
|
|
|
|
Expected<std::unique_ptr<ObjectFile>> GOFFObjOrErr =
|
|
object::ObjectFile::createGOFFObjectFile(
|
|
MemoryBufferRef(Data, "dummyGOFF"));
|
|
|
|
ASSERT_THAT_EXPECTED(
|
|
GOFFObjOrErr,
|
|
FailedWithMessage("record 2 is a continuation record that does not match "
|
|
"the type of the previous record"));
|
|
}
|
|
|
|
TEST(GOFFObjectFileTest, TwoSymbols) {
|
|
char GOFFData[GOFF::RecordLength * 4] = {0x00};
|
|
|
|
// HDR record.
|
|
GOFFData[0] = (char)0x03;
|
|
GOFFData[1] = (char)0xF0;
|
|
|
|
// ESD record 1.
|
|
GOFFData[GOFF::RecordLength] = (char)0x03;
|
|
GOFFData[GOFF::RecordLength + 3] = (char)0x00;
|
|
GOFFData[GOFF::RecordLength + 7] = (char)0x01; // ESDID.
|
|
GOFFData[GOFF::RecordLength + 71] = (char)0x01; // Size of symbol name.
|
|
GOFFData[GOFF::RecordLength + 72] = (char)0xa7; // Symbol name is x.
|
|
|
|
// ESD record 2.
|
|
GOFFData[GOFF::RecordLength * 2] = (char)0x03;
|
|
GOFFData[GOFF::RecordLength * 2 + 3] = (char)0x03;
|
|
GOFFData[GOFF::RecordLength * 2 + 7] = (char)0x02; // ESDID.
|
|
GOFFData[GOFF::RecordLength * 2 + 11] = (char)0x01; // Parent ESDID.
|
|
GOFFData[GOFF::RecordLength * 2 + 71] = (char)0x05; // Size of symbol name.
|
|
GOFFData[GOFF::RecordLength * 2 + 72] = (char)0xC8; // Symbol name is Hello.
|
|
GOFFData[GOFF::RecordLength * 2 + 73] = (char)0x85;
|
|
GOFFData[GOFF::RecordLength * 2 + 74] = (char)0x93;
|
|
GOFFData[GOFF::RecordLength * 2 + 75] = (char)0x93;
|
|
GOFFData[GOFF::RecordLength * 2 + 76] = (char)0x96;
|
|
|
|
// END record.
|
|
GOFFData[GOFF::RecordLength * 3] = (char)0x03;
|
|
GOFFData[GOFF::RecordLength * 3 + 1] = (char)0x40;
|
|
|
|
StringRef Data(GOFFData, GOFF::RecordLength * 4);
|
|
|
|
Expected<std::unique_ptr<ObjectFile>> GOFFObjOrErr =
|
|
object::ObjectFile::createGOFFObjectFile(
|
|
MemoryBufferRef(Data, "dummyGOFF"));
|
|
|
|
ASSERT_THAT_EXPECTED(GOFFObjOrErr, Succeeded());
|
|
|
|
GOFFObjectFile *GOFFObj = dyn_cast<GOFFObjectFile>((*GOFFObjOrErr).get());
|
|
|
|
for (SymbolRef Symbol : GOFFObj->symbols()) {
|
|
Expected<StringRef> SymbolNameOrErr = GOFFObj->getSymbolName(Symbol);
|
|
ASSERT_THAT_EXPECTED(SymbolNameOrErr, Succeeded());
|
|
StringRef SymbolName = SymbolNameOrErr.get();
|
|
EXPECT_EQ(SymbolName, "Hello");
|
|
}
|
|
}
|
|
|
|
TEST(GOFFObjectFileTest, InvalidSymbolType) {
|
|
char GOFFData[GOFF::RecordLength * 3] = {0x00};
|
|
|
|
// HDR record.
|
|
GOFFData[0] = (char)0x03;
|
|
GOFFData[1] = (char)0xF0;
|
|
|
|
// ESD record.
|
|
GOFFData[GOFF::RecordLength] = (char)0x03;
|
|
GOFFData[GOFF::RecordLength + 3] = (char)0x05;
|
|
GOFFData[GOFF::RecordLength + 7] = (char)0x01;
|
|
GOFFData[GOFF::RecordLength + 11] = (char)0x01;
|
|
GOFFData[GOFF::RecordLength + 71] = (char)0x01; // Size of symbol name.
|
|
GOFFData[GOFF::RecordLength + 72] = (char)0xC8; // Symbol name.
|
|
|
|
// END record.
|
|
GOFFData[GOFF::RecordLength * 2] = (char)0x03;
|
|
GOFFData[GOFF::RecordLength * 2 + 1] = (char)0x40;
|
|
|
|
StringRef Data(GOFFData, GOFF::RecordLength * 3);
|
|
|
|
Expected<std::unique_ptr<ObjectFile>> GOFFObjOrErr =
|
|
object::ObjectFile::createGOFFObjectFile(
|
|
MemoryBufferRef(Data, "dummyGOFF"));
|
|
|
|
ASSERT_THAT_EXPECTED(GOFFObjOrErr, Succeeded());
|
|
|
|
GOFFObjectFile *GOFFObj = dyn_cast<GOFFObjectFile>((*GOFFObjOrErr).get());
|
|
|
|
for (SymbolRef Symbol : GOFFObj->symbols()) {
|
|
Expected<SymbolRef::Type> SymbolType = Symbol.getType();
|
|
EXPECT_THAT_EXPECTED(
|
|
SymbolType,
|
|
FailedWithMessage("ESD record 1 has invalid symbol type 0x05"));
|
|
|
|
Expected<section_iterator> SymSI = Symbol.getSection();
|
|
ASSERT_THAT_EXPECTED(
|
|
SymSI,
|
|
FailedWithMessage(
|
|
"symbol with ESD id 1 refers to invalid section with ESD id 1"));
|
|
}
|
|
}
|
|
|
|
TEST(GOFFObjectFileTest, InvalidERSymbolType) {
|
|
char GOFFData[GOFF::RecordLength * 3] = {0x00};
|
|
|
|
// HDR record.
|
|
GOFFData[0] = (char)0x03;
|
|
GOFFData[1] = (char)0xF0;
|
|
|
|
// ESD record.
|
|
GOFFData[GOFF::RecordLength] = (char)0x03;
|
|
GOFFData[GOFF::RecordLength + 3] = (char)0x04;
|
|
GOFFData[GOFF::RecordLength + 7] = (char)0x01;
|
|
GOFFData[GOFF::RecordLength + 11] = (char)0x01;
|
|
GOFFData[GOFF::RecordLength + 63] = (char)0x03; // Unknown executable type.
|
|
GOFFData[GOFF::RecordLength + 71] = (char)0x01; // Size of symbol name.
|
|
GOFFData[GOFF::RecordLength + 72] = (char)0xC8; // Symbol name.
|
|
|
|
// END record.
|
|
GOFFData[GOFF::RecordLength * 2] = (char)0x03;
|
|
GOFFData[GOFF::RecordLength * 2 + 1] = (char)0x40;
|
|
|
|
StringRef Data(GOFFData, GOFF::RecordLength * 3);
|
|
|
|
Expected<std::unique_ptr<ObjectFile>> GOFFObjOrErr =
|
|
object::ObjectFile::createGOFFObjectFile(
|
|
MemoryBufferRef(Data, "dummyGOFF"));
|
|
|
|
ASSERT_THAT_EXPECTED(GOFFObjOrErr, Succeeded());
|
|
|
|
GOFFObjectFile *GOFFObj = dyn_cast<GOFFObjectFile>((*GOFFObjOrErr).get());
|
|
|
|
for (SymbolRef Symbol : GOFFObj->symbols()) {
|
|
Expected<SymbolRef::Type> SymbolType = Symbol.getType();
|
|
EXPECT_THAT_EXPECTED(
|
|
SymbolType,
|
|
FailedWithMessage("ESD record 1 has unknown Executable type 0x03"));
|
|
}
|
|
}
|
|
|
|
TEST(GOFFObjectFileTest, TXTConstruct) {
|
|
char GOFFData[GOFF::RecordLength * 6] = {};
|
|
|
|
// HDR record.
|
|
GOFFData[0] = (char)0x03;
|
|
GOFFData[1] = (char)0xF0;
|
|
GOFFData[50] = (char)0x01;
|
|
|
|
// ESD record.
|
|
GOFFData[GOFF::RecordLength] = (char)0x03;
|
|
GOFFData[GOFF::RecordLength + 7] = (char)0x01; // ESDID.
|
|
GOFFData[GOFF::RecordLength + 71] = (char)0x05; // Size of symbol name.
|
|
GOFFData[GOFF::RecordLength + 72] = (char)0xa5; // Symbol name is v.
|
|
GOFFData[GOFF::RecordLength + 73] = (char)0x81; // Symbol name is a.
|
|
GOFFData[GOFF::RecordLength + 74] = (char)0x99; // Symbol name is r.
|
|
GOFFData[GOFF::RecordLength + 75] = (char)0x7b; // Symbol name is #.
|
|
GOFFData[GOFF::RecordLength + 76] = (char)0x83; // Symbol name is c.
|
|
|
|
// ESD record.
|
|
GOFFData[GOFF::RecordLength * 2] = (char)0x03;
|
|
GOFFData[GOFF::RecordLength * 2 + 3] = (char)0x01;
|
|
GOFFData[GOFF::RecordLength * 2 + 7] = (char)0x02; // ESDID.
|
|
GOFFData[GOFF::RecordLength * 2 + 11] = (char)0x01; // Parent ESDID.
|
|
GOFFData[GOFF::RecordLength * 2 + 27] = (char)0x08; // Length.
|
|
GOFFData[GOFF::RecordLength * 2 + 40] = (char)0x01; // Name Space ID.
|
|
GOFFData[GOFF::RecordLength * 2 + 41] = (char)0x80;
|
|
GOFFData[GOFF::RecordLength * 2 + 60] = (char)0x04; // Size of symbol name.
|
|
GOFFData[GOFF::RecordLength * 2 + 61] = (char)0x04; // Size of symbol name.
|
|
GOFFData[GOFF::RecordLength * 2 + 63] = (char)0x0a; // Size of symbol name.
|
|
GOFFData[GOFF::RecordLength * 2 + 66] = (char)0x03; // Size of symbol name.
|
|
GOFFData[GOFF::RecordLength * 2 + 71] = (char)0x08; // Size of symbol name.
|
|
GOFFData[GOFF::RecordLength * 2 + 72] = (char)0xc3; // Symbol name is c.
|
|
GOFFData[GOFF::RecordLength * 2 + 73] = (char)0x6d; // Symbol name is _.
|
|
GOFFData[GOFF::RecordLength * 2 + 74] = (char)0xc3; // Symbol name is c.
|
|
GOFFData[GOFF::RecordLength * 2 + 75] = (char)0xd6; // Symbol name is o.
|
|
GOFFData[GOFF::RecordLength * 2 + 76] = (char)0xc4; // Symbol name is D.
|
|
GOFFData[GOFF::RecordLength * 2 + 77] = (char)0xc5; // Symbol name is E.
|
|
GOFFData[GOFF::RecordLength * 2 + 78] = (char)0xf6; // Symbol name is 6.
|
|
GOFFData[GOFF::RecordLength * 2 + 79] = (char)0xf4; // Symbol name is 4.
|
|
|
|
// ESD record.
|
|
GOFFData[GOFF::RecordLength * 3] = (char)0x03;
|
|
GOFFData[GOFF::RecordLength * 3 + 3] = (char)0x02;
|
|
GOFFData[GOFF::RecordLength * 3 + 7] = (char)0x03; // ESDID.
|
|
GOFFData[GOFF::RecordLength * 3 + 11] = (char)0x02; // Parent ESDID.
|
|
GOFFData[GOFF::RecordLength * 3 + 71] = (char)0x05; // Size of symbol name.
|
|
GOFFData[GOFF::RecordLength * 3 + 72] = (char)0xa5; // Symbol name is v.
|
|
GOFFData[GOFF::RecordLength * 3 + 73] = (char)0x81; // Symbol name is a.
|
|
GOFFData[GOFF::RecordLength * 3 + 74] = (char)0x99; // Symbol name is r.
|
|
GOFFData[GOFF::RecordLength * 3 + 75] = (char)0x7b; // Symbol name is #.
|
|
GOFFData[GOFF::RecordLength * 3 + 76] = (char)0x83; // Symbol name is c.
|
|
|
|
// TXT record.
|
|
GOFFData[GOFF::RecordLength * 4] = (char)0x03;
|
|
GOFFData[GOFF::RecordLength * 4 + 1] = (char)0x10;
|
|
GOFFData[GOFF::RecordLength * 4 + 7] = (char)0x02;
|
|
GOFFData[GOFF::RecordLength * 4 + 23] = (char)0x08; // Data Length.
|
|
GOFFData[GOFF::RecordLength * 4 + 24] = (char)0x12;
|
|
GOFFData[GOFF::RecordLength * 4 + 25] = (char)0x34;
|
|
GOFFData[GOFF::RecordLength * 4 + 26] = (char)0x56;
|
|
GOFFData[GOFF::RecordLength * 4 + 27] = (char)0x78;
|
|
GOFFData[GOFF::RecordLength * 4 + 28] = (char)0x9a;
|
|
GOFFData[GOFF::RecordLength * 4 + 29] = (char)0xbc;
|
|
GOFFData[GOFF::RecordLength * 4 + 30] = (char)0xde;
|
|
GOFFData[GOFF::RecordLength * 4 + 31] = (char)0xf0;
|
|
|
|
// END record.
|
|
GOFFData[GOFF::RecordLength * 5] = (char)0x03;
|
|
GOFFData[GOFF::RecordLength * 5 + 1] = (char)0x40;
|
|
GOFFData[GOFF::RecordLength * 5 + 11] = (char)0x06;
|
|
|
|
StringRef Data(GOFFData, GOFF::RecordLength * 6);
|
|
|
|
Expected<std::unique_ptr<ObjectFile>> GOFFObjOrErr =
|
|
object::ObjectFile::createGOFFObjectFile(
|
|
MemoryBufferRef(Data, "dummyGOFF"));
|
|
|
|
ASSERT_THAT_EXPECTED(GOFFObjOrErr, Succeeded());
|
|
|
|
GOFFObjectFile *GOFFObj = dyn_cast<GOFFObjectFile>((*GOFFObjOrErr).get());
|
|
auto Symbols = GOFFObj->symbols();
|
|
ASSERT_EQ(std::distance(Symbols.begin(), Symbols.end()), 1);
|
|
SymbolRef Symbol = *Symbols.begin();
|
|
Expected<StringRef> SymbolNameOrErr = GOFFObj->getSymbolName(Symbol);
|
|
ASSERT_THAT_EXPECTED(SymbolNameOrErr, Succeeded());
|
|
StringRef SymbolName = SymbolNameOrErr.get();
|
|
EXPECT_EQ(SymbolName, "var#c");
|
|
|
|
auto Sections = GOFFObj->sections();
|
|
ASSERT_EQ(std::distance(Sections.begin(), Sections.end()), 1);
|
|
SectionRef Section = *Sections.begin();
|
|
Expected<StringRef> SectionContent = Section.getContents();
|
|
ASSERT_THAT_EXPECTED(SectionContent, Succeeded());
|
|
StringRef Contents = SectionContent.get();
|
|
EXPECT_EQ(Contents, "\x12\x34\x56\x78\x9a\xbc\xde\xf0");
|
|
}
|