mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2025-01-26 19:36:28 +00:00
[objcopy][NFC] Move NameOrPattern::create() into CommonConfig.h
While moving objcopy into separate library(D88827), NameOrPattern::create() was mistakenly placed into ObjcopyOptions.cpp. This patch moves the NameOrPattern::create() into CommonConfig.h. Additionally it adds test for using NameOrPattern. Differential Revision: https://reviews.llvm.org/D121005
This commit is contained in:
parent
e0cc28dfdc
commit
2dc4a80ec0
@ -37,6 +37,7 @@ source_group("Source Files\\XCOFF" REGULAR_EXPRESSION
|
|||||||
|
|
||||||
add_llvm_component_library(LLVMObjCopy
|
add_llvm_component_library(LLVMObjCopy
|
||||||
Archive.cpp
|
Archive.cpp
|
||||||
|
CommonConfig.cpp
|
||||||
ObjCopy.cpp
|
ObjCopy.cpp
|
||||||
ConfigManager.cpp
|
ConfigManager.cpp
|
||||||
COFF/COFFObjcopy.cpp
|
COFF/COFFObjcopy.cpp
|
||||||
|
50
llvm/lib/ObjCopy/CommonConfig.cpp
Normal file
50
llvm/lib/ObjCopy/CommonConfig.cpp
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
//===- CommonConfig.cpp ---------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// 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/ObjCopy/CommonConfig.h"
|
||||||
|
|
||||||
|
namespace llvm {
|
||||||
|
namespace objcopy {
|
||||||
|
|
||||||
|
Expected<NameOrPattern>
|
||||||
|
NameOrPattern::create(StringRef Pattern, MatchStyle MS,
|
||||||
|
function_ref<Error(Error)> ErrorCallback) {
|
||||||
|
switch (MS) {
|
||||||
|
case MatchStyle::Literal:
|
||||||
|
return NameOrPattern(Pattern);
|
||||||
|
case MatchStyle::Wildcard: {
|
||||||
|
SmallVector<char, 32> Data;
|
||||||
|
bool IsPositiveMatch = true;
|
||||||
|
if (Pattern[0] == '!') {
|
||||||
|
IsPositiveMatch = false;
|
||||||
|
Pattern = Pattern.drop_front();
|
||||||
|
}
|
||||||
|
Expected<GlobPattern> GlobOrErr = GlobPattern::create(Pattern);
|
||||||
|
|
||||||
|
// If we couldn't create it as a glob, report the error, but try again
|
||||||
|
// with a literal if the error reporting is non-fatal.
|
||||||
|
if (!GlobOrErr) {
|
||||||
|
if (Error E = ErrorCallback(GlobOrErr.takeError()))
|
||||||
|
return std::move(E);
|
||||||
|
return create(Pattern, MatchStyle::Literal, ErrorCallback);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NameOrPattern(std::make_shared<GlobPattern>(*GlobOrErr),
|
||||||
|
IsPositiveMatch);
|
||||||
|
}
|
||||||
|
case MatchStyle::Regex: {
|
||||||
|
SmallVector<char, 32> Data;
|
||||||
|
return NameOrPattern(std::make_shared<Regex>(
|
||||||
|
("^" + Pattern.ltrim('^').rtrim('$') + "$").toStringRef(Data)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
llvm_unreachable("Unhandled llvm.objcopy.MatchStyle enum");
|
||||||
|
}
|
||||||
|
|
||||||
|
} // end namespace objcopy
|
||||||
|
} // end namespace llvm
|
@ -367,41 +367,6 @@ static Error addSymbolsFromFile(NameMatcher &Symbols, BumpPtrAllocator &Alloc,
|
|||||||
return Error::success();
|
return Error::success();
|
||||||
}
|
}
|
||||||
|
|
||||||
Expected<NameOrPattern>
|
|
||||||
NameOrPattern::create(StringRef Pattern, MatchStyle MS,
|
|
||||||
function_ref<Error(Error)> ErrorCallback) {
|
|
||||||
switch (MS) {
|
|
||||||
case MatchStyle::Literal:
|
|
||||||
return NameOrPattern(Pattern);
|
|
||||||
case MatchStyle::Wildcard: {
|
|
||||||
SmallVector<char, 32> Data;
|
|
||||||
bool IsPositiveMatch = true;
|
|
||||||
if (Pattern[0] == '!') {
|
|
||||||
IsPositiveMatch = false;
|
|
||||||
Pattern = Pattern.drop_front();
|
|
||||||
}
|
|
||||||
Expected<GlobPattern> GlobOrErr = GlobPattern::create(Pattern);
|
|
||||||
|
|
||||||
// If we couldn't create it as a glob, report the error, but try again with
|
|
||||||
// a literal if the error reporting is non-fatal.
|
|
||||||
if (!GlobOrErr) {
|
|
||||||
if (Error E = ErrorCallback(GlobOrErr.takeError()))
|
|
||||||
return std::move(E);
|
|
||||||
return create(Pattern, MatchStyle::Literal, ErrorCallback);
|
|
||||||
}
|
|
||||||
|
|
||||||
return NameOrPattern(std::make_shared<GlobPattern>(*GlobOrErr),
|
|
||||||
IsPositiveMatch);
|
|
||||||
}
|
|
||||||
case MatchStyle::Regex: {
|
|
||||||
SmallVector<char, 32> Data;
|
|
||||||
return NameOrPattern(std::make_shared<Regex>(
|
|
||||||
("^" + Pattern.ltrim('^').rtrim('$') + "$").toStringRef(Data)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
llvm_unreachable("Unhandled llvm.objcopy.MatchStyle enum");
|
|
||||||
}
|
|
||||||
|
|
||||||
static Error addSymbolsToRenameFromFile(StringMap<StringRef> &SymbolsToRename,
|
static Error addSymbolsToRenameFromFile(StringMap<StringRef> &SymbolsToRename,
|
||||||
BumpPtrAllocator &Alloc,
|
BumpPtrAllocator &Alloc,
|
||||||
StringRef Filename) {
|
StringRef Filename) {
|
||||||
|
@ -21,41 +21,7 @@ using namespace object;
|
|||||||
using namespace objcopy;
|
using namespace objcopy;
|
||||||
using namespace yaml;
|
using namespace yaml;
|
||||||
|
|
||||||
void copySimpleInMemoryFileImpl(
|
const char *SimpleFileCOFFYAML = R"(
|
||||||
const char *YamlCreationString,
|
|
||||||
std::function<bool(const Binary &File)> IsValidFormat) {
|
|
||||||
auto ErrHandler = [&](const Twine &Msg) { FAIL() << "Error: " << Msg; };
|
|
||||||
|
|
||||||
// Create Object file from YAML description.
|
|
||||||
SmallVector<char> Storage;
|
|
||||||
std::unique_ptr<ObjectFile> Obj =
|
|
||||||
yaml2ObjectFile(Storage, YamlCreationString, ErrHandler);
|
|
||||||
ASSERT_TRUE(Obj);
|
|
||||||
ASSERT_TRUE(IsValidFormat(*Obj));
|
|
||||||
|
|
||||||
ConfigManager Config;
|
|
||||||
Config.Common.OutputFilename = "a.out";
|
|
||||||
|
|
||||||
// Call executeObjcopyOnBinary()
|
|
||||||
SmallVector<char> DataVector;
|
|
||||||
raw_svector_ostream OutStream(DataVector);
|
|
||||||
Error Err = objcopy::executeObjcopyOnBinary(Config, *Obj.get(), OutStream);
|
|
||||||
ASSERT_FALSE(std::move(Err));
|
|
||||||
|
|
||||||
MemoryBufferRef Buffer(StringRef(DataVector.data(), DataVector.size()),
|
|
||||||
Config.Common.OutputFilename);
|
|
||||||
|
|
||||||
// Check copied file.
|
|
||||||
Expected<std::unique_ptr<Binary>> Result = createBinary(Buffer);
|
|
||||||
ASSERT_THAT_EXPECTED(Result, Succeeded());
|
|
||||||
ASSERT_TRUE(IsValidFormat(**Result));
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(CopySimpleInMemoryFile, COFF) {
|
|
||||||
SCOPED_TRACE("CopySimpleInMemoryFileCOFF");
|
|
||||||
|
|
||||||
copySimpleInMemoryFileImpl(
|
|
||||||
R"(
|
|
||||||
--- !COFF
|
--- !COFF
|
||||||
header:
|
header:
|
||||||
Machine: IMAGE_FILE_MACHINE_AMD64
|
Machine: IMAGE_FILE_MACHINE_AMD64
|
||||||
@ -67,161 +33,22 @@ sections:
|
|||||||
SectionData: E800000000C3C3C3
|
SectionData: E800000000C3C3C3
|
||||||
symbols:
|
symbols:
|
||||||
...
|
...
|
||||||
)",
|
)";
|
||||||
[](const Binary &File) { return File.isCOFF(); });
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(CopySimpleInMemoryFile, ELF) {
|
const char *SimpleFileELFYAML = R"(
|
||||||
SCOPED_TRACE("CopySimpleInMemoryFileELF");
|
|
||||||
|
|
||||||
copySimpleInMemoryFileImpl(
|
|
||||||
R"(
|
|
||||||
--- !ELF
|
--- !ELF
|
||||||
FileHeader:
|
FileHeader:
|
||||||
Class: ELFCLASS64
|
Class: ELFCLASS64
|
||||||
Data: ELFDATA2LSB
|
Data: ELFDATA2LSB
|
||||||
Type: ET_REL)",
|
Type: ET_REL
|
||||||
[](const Binary &File) { return File.isELF(); });
|
Sections:
|
||||||
}
|
|
||||||
|
|
||||||
TEST(CopySimpleInMemoryFile, MachO) {
|
|
||||||
SCOPED_TRACE("CopySimpleInMemoryFileMachO");
|
|
||||||
|
|
||||||
copySimpleInMemoryFileImpl(
|
|
||||||
R"(
|
|
||||||
--- !mach-o
|
|
||||||
FileHeader:
|
|
||||||
magic: 0xFEEDFACF
|
|
||||||
cputype: 0x01000007
|
|
||||||
cpusubtype: 0x80000003
|
|
||||||
filetype: 0x00000002
|
|
||||||
ncmds: 0
|
|
||||||
sizeofcmds: 0
|
|
||||||
flags: 0x00218085
|
|
||||||
reserved: 0x00000000
|
|
||||||
...
|
|
||||||
)",
|
|
||||||
[](const Binary &File) { return File.isMachO(); });
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(CopySimpleInMemoryFile, Wasm) {
|
|
||||||
SCOPED_TRACE("CopySimpleInMemoryFileWasm");
|
|
||||||
|
|
||||||
copySimpleInMemoryFileImpl(
|
|
||||||
R"(
|
|
||||||
--- !WASM
|
|
||||||
FileHeader:
|
|
||||||
Version: 0x00000001
|
|
||||||
...
|
|
||||||
)",
|
|
||||||
[](const Binary &File) { return File.isWasm(); });
|
|
||||||
}
|
|
||||||
|
|
||||||
enum Action : uint8_t { AddSection, UpdateSection };
|
|
||||||
|
|
||||||
void addOrUpdateSectionToFileImpl(
|
|
||||||
const char *YamlCreationString,
|
|
||||||
std::function<bool(const Binary &File)> IsValidFormat,
|
|
||||||
StringRef NewSectionName, StringRef NewSectionData, Action SectionAction) {
|
|
||||||
auto ErrHandler = [&](const Twine &Msg) { FAIL() << "Error: " << Msg; };
|
|
||||||
|
|
||||||
// Create Object file from YAML description.
|
|
||||||
SmallVector<char> Storage;
|
|
||||||
std::unique_ptr<ObjectFile> Obj =
|
|
||||||
yaml2ObjectFile(Storage, YamlCreationString, ErrHandler);
|
|
||||||
ASSERT_TRUE(Obj);
|
|
||||||
ASSERT_TRUE(IsValidFormat(*Obj));
|
|
||||||
|
|
||||||
std::unique_ptr<MemoryBuffer> NewSectionBuffer =
|
|
||||||
MemoryBuffer::getMemBuffer(NewSectionData, NewSectionName, false);
|
|
||||||
std::string Name;
|
|
||||||
if (Obj->isMachO())
|
|
||||||
Name = "__TEXT," + NewSectionName.str();
|
|
||||||
else
|
|
||||||
Name = NewSectionName.str();
|
|
||||||
|
|
||||||
ConfigManager Config;
|
|
||||||
Config.Common.OutputFilename = "a.out";
|
|
||||||
if (SectionAction == AddSection)
|
|
||||||
Config.Common.AddSection.push_back({Name, std::move(NewSectionBuffer)});
|
|
||||||
else
|
|
||||||
Config.Common.UpdateSection.push_back({Name, std::move(NewSectionBuffer)});
|
|
||||||
|
|
||||||
// Call executeObjcopyOnBinary()
|
|
||||||
SmallVector<char> DataVector;
|
|
||||||
raw_svector_ostream OutStream(DataVector);
|
|
||||||
Error Err = objcopy::executeObjcopyOnBinary(Config, *Obj.get(), OutStream);
|
|
||||||
ASSERT_FALSE(std::move(Err));
|
|
||||||
|
|
||||||
MemoryBufferRef Buffer(StringRef(DataVector.data(), DataVector.size()),
|
|
||||||
Config.Common.OutputFilename);
|
|
||||||
|
|
||||||
// Check copied file.
|
|
||||||
Expected<std::unique_ptr<Binary>> Result = createBinary(Buffer);
|
|
||||||
ASSERT_THAT_EXPECTED(Result, Succeeded());
|
|
||||||
ASSERT_TRUE(IsValidFormat(**Result));
|
|
||||||
ASSERT_TRUE((*Result)->isObject());
|
|
||||||
|
|
||||||
// Check that copied file has the new section.
|
|
||||||
bool HasNewSection = false;
|
|
||||||
for (const object::SectionRef &Sect :
|
|
||||||
static_cast<ObjectFile *>((*Result).get())->sections()) {
|
|
||||||
Expected<StringRef> SectNameOrErr = Sect.getName();
|
|
||||||
ASSERT_THAT_EXPECTED(SectNameOrErr, Succeeded());
|
|
||||||
|
|
||||||
if (*SectNameOrErr == NewSectionName) {
|
|
||||||
HasNewSection = true;
|
|
||||||
Expected<StringRef> SectionData = Sect.getContents();
|
|
||||||
ASSERT_THAT_EXPECTED(SectionData, Succeeded());
|
|
||||||
EXPECT_TRUE(Sect.getSize() == NewSectionData.size());
|
|
||||||
EXPECT_TRUE(memcmp(SectionData->data(), NewSectionData.data(),
|
|
||||||
NewSectionData.size()) == 0);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
EXPECT_TRUE(HasNewSection);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(AddSection, COFF) {
|
|
||||||
SCOPED_TRACE("addSectionToFileCOFF");
|
|
||||||
|
|
||||||
addOrUpdateSectionToFileImpl(
|
|
||||||
R"(
|
|
||||||
--- !COFF
|
|
||||||
header:
|
|
||||||
Machine: IMAGE_FILE_MACHINE_AMD64
|
|
||||||
Characteristics: [ ]
|
|
||||||
sections:
|
|
||||||
- Name: .text
|
- Name: .text
|
||||||
Characteristics: [ ]
|
Type: SHT_PROGBITS
|
||||||
Alignment: 4
|
Flags: [ SHF_ALLOC ]
|
||||||
SectionData: E800000000C3C3C3
|
Content: "12345678"
|
||||||
symbols:
|
)";
|
||||||
...
|
|
||||||
)",
|
|
||||||
[](const Binary &File) { return File.isCOFF(); }, ".foo", "1234",
|
|
||||||
AddSection);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(AddSection, ELF) {
|
const char *SimpleFileMachOYAML = R"(
|
||||||
SCOPED_TRACE("addSectionToFileELF");
|
|
||||||
|
|
||||||
addOrUpdateSectionToFileImpl(
|
|
||||||
R"(
|
|
||||||
--- !ELF
|
|
||||||
FileHeader:
|
|
||||||
Class: ELFCLASS64
|
|
||||||
Data: ELFDATA2LSB
|
|
||||||
Type: ET_REL)",
|
|
||||||
[](const Binary &File) { return File.isELF(); }, ".foo", "1234",
|
|
||||||
AddSection);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(AddSection, MachO) {
|
|
||||||
SCOPED_TRACE("addSectionToFileMachO");
|
|
||||||
|
|
||||||
addOrUpdateSectionToFileImpl(
|
|
||||||
R"(
|
|
||||||
--- !mach-o
|
--- !mach-o
|
||||||
FileHeader:
|
FileHeader:
|
||||||
magic: 0xFEEDFACF
|
magic: 0xFEEDFACF
|
||||||
@ -259,109 +86,313 @@ LoadCommands:
|
|||||||
reserved2: 0x00000000
|
reserved2: 0x00000000
|
||||||
reserved3: 0x00000000
|
reserved3: 0x00000000
|
||||||
...
|
...
|
||||||
)",
|
)";
|
||||||
[](const Binary &File) { return File.isMachO(); }, "__foo", "1234",
|
|
||||||
AddSection);
|
const char *SimpleFileWasmYAML = R"(
|
||||||
|
--- !WASM
|
||||||
|
FileHeader:
|
||||||
|
Version: 0x00000001
|
||||||
|
Sections:
|
||||||
|
- Type: CUSTOM
|
||||||
|
Name: text
|
||||||
|
Payload: ABC123
|
||||||
|
...
|
||||||
|
)";
|
||||||
|
|
||||||
|
// Create ObjectFile from \p YamlCreationString and do validation using \p
|
||||||
|
// IsValidFormat checker. \p Storage is a storage for data. \returns created
|
||||||
|
// ObjectFile.
|
||||||
|
Expected<std::unique_ptr<ObjectFile>> createObjectFileFromYamlDescription(
|
||||||
|
const char *YamlCreationString, SmallVector<char> &Storage,
|
||||||
|
function_ref<bool(const Binary &File)> IsValidFormat) {
|
||||||
|
auto ErrHandler = [&](const Twine &Msg) { FAIL() << "Error: " << Msg; };
|
||||||
|
|
||||||
|
std::unique_ptr<ObjectFile> Obj =
|
||||||
|
yaml2ObjectFile(Storage, YamlCreationString, ErrHandler);
|
||||||
|
if (!Obj)
|
||||||
|
return createError("could not create ObjectFile from yaml description");
|
||||||
|
|
||||||
|
if (!IsValidFormat(*Obj))
|
||||||
|
return createError("wrong file format");
|
||||||
|
|
||||||
|
return Obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call objcopy::executeObjcopyOnBinary for \p Config and \p In. \p DataVector
|
||||||
|
// is a holder for data. \returns Binary for copied data.
|
||||||
|
Expected<std::unique_ptr<Binary>>
|
||||||
|
callObjCopy(ConfigManager &Config, object::Binary &In,
|
||||||
|
SmallVector<char> &DataVector,
|
||||||
|
function_ref<bool(const Binary &File)> IsValidFormat) {
|
||||||
|
raw_svector_ostream OutStream(DataVector);
|
||||||
|
|
||||||
|
if (Error Err = objcopy::executeObjcopyOnBinary(Config, In, OutStream))
|
||||||
|
return std::move(Err);
|
||||||
|
|
||||||
|
MemoryBufferRef Buffer(StringRef(DataVector.data(), DataVector.size()),
|
||||||
|
Config.Common.OutputFilename);
|
||||||
|
|
||||||
|
Expected<std::unique_ptr<Binary>> Result = createBinary(Buffer);
|
||||||
|
|
||||||
|
// Check copied file.
|
||||||
|
if (!Result)
|
||||||
|
return Result;
|
||||||
|
|
||||||
|
if (!IsValidFormat(**Result))
|
||||||
|
return createError("wrong file format");
|
||||||
|
|
||||||
|
if (!(*Result)->isObject())
|
||||||
|
return createError("binary is not object file");
|
||||||
|
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// \returns true if specified \p File has a section named \p SectionName.
|
||||||
|
bool hasSection(ObjectFile &File, StringRef SectionName) {
|
||||||
|
for (const object::SectionRef &Sec : File.sections()) {
|
||||||
|
Expected<StringRef> CurSecNameOrErr = Sec.getName();
|
||||||
|
if (!CurSecNameOrErr)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (*CurSecNameOrErr == SectionName)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check that specified \p File has a section \p SectionName and its data
|
||||||
|
// matches \p SectionData.
|
||||||
|
void checkSectionData(ObjectFile &File, StringRef SectionName,
|
||||||
|
StringRef SectionData) {
|
||||||
|
for (const object::SectionRef &Sec : File.sections()) {
|
||||||
|
Expected<StringRef> CurSecNameOrErr = Sec.getName();
|
||||||
|
ASSERT_THAT_EXPECTED(CurSecNameOrErr, Succeeded());
|
||||||
|
|
||||||
|
if (*CurSecNameOrErr == SectionName) {
|
||||||
|
Expected<StringRef> CurSectionData = Sec.getContents();
|
||||||
|
ASSERT_THAT_EXPECTED(CurSectionData, Succeeded());
|
||||||
|
EXPECT_TRUE(Sec.getSize() == SectionData.size());
|
||||||
|
EXPECT_TRUE(memcmp(CurSectionData->data(), SectionData.data(),
|
||||||
|
SectionData.size()) == 0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Section SectionName must be presented.
|
||||||
|
EXPECT_TRUE(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void copySimpleInMemoryFileImpl(
|
||||||
|
const char *YamlCreationString,
|
||||||
|
function_ref<bool(const Binary &File)> IsValidFormat) {
|
||||||
|
SCOPED_TRACE("copySimpleInMemoryFileImpl");
|
||||||
|
|
||||||
|
// Create Object file from YAML description.
|
||||||
|
SmallVector<char> Storage;
|
||||||
|
Expected<std::unique_ptr<ObjectFile>> Obj =
|
||||||
|
createObjectFileFromYamlDescription(YamlCreationString, Storage,
|
||||||
|
IsValidFormat);
|
||||||
|
ASSERT_THAT_EXPECTED(Obj, Succeeded());
|
||||||
|
|
||||||
|
ConfigManager Config;
|
||||||
|
Config.Common.OutputFilename = "a.out";
|
||||||
|
|
||||||
|
// Call executeObjcopyOnBinary()
|
||||||
|
SmallVector<char> DataVector;
|
||||||
|
Expected<std::unique_ptr<Binary>> Result =
|
||||||
|
callObjCopy(Config, *Obj.get(), DataVector, IsValidFormat);
|
||||||
|
ASSERT_THAT_EXPECTED(Result, Succeeded());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(CopySimpleInMemoryFile, COFF) {
|
||||||
|
SCOPED_TRACE("CopySimpleInMemoryFileCOFF");
|
||||||
|
|
||||||
|
copySimpleInMemoryFileImpl(SimpleFileCOFFYAML,
|
||||||
|
[](const Binary &File) { return File.isCOFF(); });
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(CopySimpleInMemoryFile, ELF) {
|
||||||
|
SCOPED_TRACE("CopySimpleInMemoryFileELF");
|
||||||
|
|
||||||
|
copySimpleInMemoryFileImpl(SimpleFileELFYAML,
|
||||||
|
[](const Binary &File) { return File.isELF(); });
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(CopySimpleInMemoryFile, MachO) {
|
||||||
|
SCOPED_TRACE("CopySimpleInMemoryFileMachO");
|
||||||
|
|
||||||
|
copySimpleInMemoryFileImpl(SimpleFileMachOYAML,
|
||||||
|
[](const Binary &File) { return File.isMachO(); });
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(CopySimpleInMemoryFile, Wasm) {
|
||||||
|
SCOPED_TRACE("CopySimpleInMemoryFileWasm");
|
||||||
|
|
||||||
|
copySimpleInMemoryFileImpl(SimpleFileWasmYAML,
|
||||||
|
[](const Binary &File) { return File.isWasm(); });
|
||||||
|
}
|
||||||
|
|
||||||
|
enum Action : uint8_t { AddSection, UpdateSection };
|
||||||
|
|
||||||
|
void addOrUpdateSectionToFileImpl(
|
||||||
|
const char *YamlCreationString,
|
||||||
|
function_ref<bool(const Binary &File)> IsValidFormat,
|
||||||
|
StringRef NewSectionName, StringRef NewSectionData, Action SectionAction) {
|
||||||
|
SCOPED_TRACE("addOrUpdateSectionToFileImpl");
|
||||||
|
|
||||||
|
// Create Object file from YAML description.
|
||||||
|
SmallVector<char> Storage;
|
||||||
|
Expected<std::unique_ptr<ObjectFile>> Obj =
|
||||||
|
createObjectFileFromYamlDescription(YamlCreationString, Storage,
|
||||||
|
IsValidFormat);
|
||||||
|
ASSERT_THAT_EXPECTED(Obj, Succeeded());
|
||||||
|
|
||||||
|
std::unique_ptr<MemoryBuffer> NewSectionBuffer =
|
||||||
|
MemoryBuffer::getMemBuffer(NewSectionData, NewSectionName, false);
|
||||||
|
std::string Name;
|
||||||
|
if ((*Obj)->isMachO())
|
||||||
|
Name = "__TEXT," + NewSectionName.str();
|
||||||
|
else
|
||||||
|
Name = NewSectionName.str();
|
||||||
|
|
||||||
|
ConfigManager Config;
|
||||||
|
Config.Common.OutputFilename = "a.out";
|
||||||
|
if (SectionAction == AddSection)
|
||||||
|
Config.Common.AddSection.push_back({Name, std::move(NewSectionBuffer)});
|
||||||
|
else
|
||||||
|
Config.Common.UpdateSection.push_back({Name, std::move(NewSectionBuffer)});
|
||||||
|
|
||||||
|
// Call executeObjcopyOnBinary()
|
||||||
|
SmallVector<char> DataVector;
|
||||||
|
Expected<std::unique_ptr<Binary>> Result =
|
||||||
|
callObjCopy(Config, *Obj.get(), DataVector, IsValidFormat);
|
||||||
|
ASSERT_THAT_EXPECTED(Result, Succeeded());
|
||||||
|
|
||||||
|
// Check that copied file has the new section.
|
||||||
|
checkSectionData(*static_cast<ObjectFile *>((*Result).get()), NewSectionName,
|
||||||
|
NewSectionData);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(AddSection, COFF) {
|
||||||
|
SCOPED_TRACE("addSectionToFileCOFF");
|
||||||
|
|
||||||
|
addOrUpdateSectionToFileImpl(
|
||||||
|
SimpleFileCOFFYAML, [](const Binary &File) { return File.isCOFF(); },
|
||||||
|
".foo", "1234", AddSection);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(AddSection, ELF) {
|
||||||
|
SCOPED_TRACE("addSectionToFileELF");
|
||||||
|
|
||||||
|
addOrUpdateSectionToFileImpl(
|
||||||
|
SimpleFileELFYAML, [](const Binary &File) { return File.isELF(); },
|
||||||
|
".foo", "1234", AddSection);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(AddSection, MachO) {
|
||||||
|
SCOPED_TRACE("addSectionToFileMachO");
|
||||||
|
|
||||||
|
addOrUpdateSectionToFileImpl(
|
||||||
|
SimpleFileMachOYAML, [](const Binary &File) { return File.isMachO(); },
|
||||||
|
"__foo", "1234", AddSection);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(AddSection, Wasm) {
|
TEST(AddSection, Wasm) {
|
||||||
SCOPED_TRACE("addSectionToFileWasm");
|
SCOPED_TRACE("addSectionToFileWasm");
|
||||||
|
|
||||||
addOrUpdateSectionToFileImpl(
|
addOrUpdateSectionToFileImpl(
|
||||||
R"(
|
SimpleFileWasmYAML, [](const Binary &File) { return File.isWasm(); },
|
||||||
--- !WASM
|
".foo", "1234", AddSection);
|
||||||
FileHeader:
|
|
||||||
Version: 0x00000001
|
|
||||||
...
|
|
||||||
)",
|
|
||||||
[](const Binary &File) { return File.isWasm(); }, ".foo", "1234",
|
|
||||||
AddSection);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(UpdateSection, COFF) {
|
TEST(UpdateSection, COFF) {
|
||||||
SCOPED_TRACE("updateSectionToFileCOFF");
|
SCOPED_TRACE("updateSectionToFileCOFF");
|
||||||
|
|
||||||
addOrUpdateSectionToFileImpl(
|
addOrUpdateSectionToFileImpl(
|
||||||
R"(
|
SimpleFileCOFFYAML, [](const Binary &File) { return File.isCOFF(); },
|
||||||
--- !COFF
|
".text", "1234", UpdateSection);
|
||||||
header:
|
|
||||||
Machine: IMAGE_FILE_MACHINE_AMD64
|
|
||||||
Characteristics: [ ]
|
|
||||||
sections:
|
|
||||||
- Name: .foo
|
|
||||||
Characteristics: [ ]
|
|
||||||
Alignment: 4
|
|
||||||
SectionData: E800000000C3C3C3
|
|
||||||
symbols:
|
|
||||||
...
|
|
||||||
)",
|
|
||||||
[](const Binary &File) { return File.isCOFF(); }, ".foo", "1234",
|
|
||||||
UpdateSection);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(UpdateSection, ELF) {
|
TEST(UpdateSection, ELF) {
|
||||||
SCOPED_TRACE("updateSectionToFileELF");
|
SCOPED_TRACE("updateSectionToFileELF");
|
||||||
|
|
||||||
addOrUpdateSectionToFileImpl(
|
addOrUpdateSectionToFileImpl(
|
||||||
R"(
|
SimpleFileELFYAML, [](const Binary &File) { return File.isELF(); },
|
||||||
--- !ELF
|
".text", "1234", UpdateSection);
|
||||||
FileHeader:
|
|
||||||
Class: ELFCLASS64
|
|
||||||
Data: ELFDATA2LSB
|
|
||||||
Type: ET_REL
|
|
||||||
Sections:
|
|
||||||
- Name: .foo
|
|
||||||
Type: SHT_PROGBITS
|
|
||||||
Flags: [ SHF_ALLOC ]
|
|
||||||
Content: "12345678"
|
|
||||||
)",
|
|
||||||
[](const Binary &File) { return File.isELF(); }, ".foo", "1234",
|
|
||||||
UpdateSection);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(UpdateSection, MachO) {
|
TEST(UpdateSection, MachO) {
|
||||||
SCOPED_TRACE("updateSectionToFileMachO");
|
SCOPED_TRACE("updateSectionToFileMachO");
|
||||||
|
|
||||||
addOrUpdateSectionToFileImpl(
|
addOrUpdateSectionToFileImpl(
|
||||||
R"(
|
SimpleFileMachOYAML, [](const Binary &File) { return File.isMachO(); },
|
||||||
--- !mach-o
|
"__text", "1234", UpdateSection);
|
||||||
FileHeader:
|
}
|
||||||
magic: 0xFEEDFACF
|
|
||||||
cputype: 0x01000007
|
void removeSectionByPatternImpl(
|
||||||
cpusubtype: 0x80000003
|
const char *YamlCreationString,
|
||||||
filetype: 0x00000001
|
function_ref<bool(const Binary &File)> IsValidFormat,
|
||||||
ncmds: 1
|
StringRef SectionWildcard, StringRef SectionName) {
|
||||||
sizeofcmds: 152
|
SCOPED_TRACE("removeSectionByPatternImpl");
|
||||||
flags: 0x00002000
|
|
||||||
reserved: 0x00000000
|
// Create Object file from YAML description.
|
||||||
LoadCommands:
|
SmallVector<char> Storage;
|
||||||
- cmd: LC_SEGMENT_64
|
Expected<std::unique_ptr<ObjectFile>> Obj =
|
||||||
cmdsize: 152
|
createObjectFileFromYamlDescription(YamlCreationString, Storage,
|
||||||
segname: __TEXT
|
IsValidFormat);
|
||||||
vmaddr: 0
|
ASSERT_THAT_EXPECTED(Obj, Succeeded());
|
||||||
vmsize: 4
|
|
||||||
fileoff: 184
|
// Check that section is present.
|
||||||
filesize: 4
|
EXPECT_TRUE(hasSection(**Obj, SectionName));
|
||||||
maxprot: 7
|
|
||||||
initprot: 7
|
Expected<NameOrPattern> Pattern = objcopy::NameOrPattern::create(
|
||||||
nsects: 1
|
SectionWildcard, objcopy::MatchStyle::Wildcard,
|
||||||
flags: 0
|
[](Error Err) { return Err; });
|
||||||
Sections:
|
|
||||||
- sectname: __foo
|
ConfigManager Config;
|
||||||
segname: __TEXT
|
Config.Common.OutputFilename = "a.out";
|
||||||
addr: 0x0000000000000000
|
EXPECT_THAT_ERROR(Config.Common.ToRemove.addMatcher(std::move(Pattern)),
|
||||||
content: 'AABBCCDD'
|
Succeeded());
|
||||||
size: 4
|
|
||||||
offset: 184
|
SmallVector<char> DataVector;
|
||||||
align: 0
|
Expected<std::unique_ptr<Binary>> Result =
|
||||||
reloff: 0x00000000
|
callObjCopy(Config, *Obj.get(), DataVector, IsValidFormat);
|
||||||
nreloc: 0
|
ASSERT_THAT_EXPECTED(Result, Succeeded());
|
||||||
flags: 0x80000400
|
|
||||||
reserved1: 0x00000000
|
// Check that section was removed.
|
||||||
reserved2: 0x00000000
|
EXPECT_FALSE(
|
||||||
reserved3: 0x00000000
|
hasSection(*static_cast<ObjectFile *>((*Result).get()), SectionName));
|
||||||
...
|
}
|
||||||
)",
|
|
||||||
[](const Binary &File) { return File.isMachO(); }, "__foo", "1234",
|
TEST(RemoveSectionByPattern, COFF) {
|
||||||
UpdateSection);
|
SCOPED_TRACE("removeSectionByPatternCOFF");
|
||||||
|
|
||||||
|
removeSectionByPatternImpl(
|
||||||
|
SimpleFileCOFFYAML, [](const Binary &File) { return File.isCOFF(); },
|
||||||
|
"\\.text*", ".text");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(RemoveSectionByPattern, ELF) {
|
||||||
|
SCOPED_TRACE("removeSectionByPatternELF");
|
||||||
|
|
||||||
|
removeSectionByPatternImpl(
|
||||||
|
SimpleFileELFYAML, [](const Binary &File) { return File.isELF(); },
|
||||||
|
"\\.text*", ".text");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(RemoveSectionByPattern, MachO) {
|
||||||
|
SCOPED_TRACE("removeSectionByPatternMachO");
|
||||||
|
|
||||||
|
removeSectionByPatternImpl(
|
||||||
|
SimpleFileMachOYAML, [](const Binary &File) { return File.isMachO(); },
|
||||||
|
"__TEXT,__text*", "__text");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(RemoveSectionByPattern, Wasm) {
|
||||||
|
SCOPED_TRACE("removeSectionByPatternWasm");
|
||||||
|
|
||||||
|
removeSectionByPatternImpl(
|
||||||
|
SimpleFileWasmYAML, [](const Binary &File) { return File.isWasm(); },
|
||||||
|
"text*", "text");
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user