xref: /llvm-project/llvm/unittests/ObjCopy/ObjCopyTest.cpp (revision 3b7bfeb483e78d355ec3527aa31786e2545470ea)
1f75da0c8SAlexey Lapshin //===- ObjCopyTest.cpp ----------------------------------------------------===//
2f75da0c8SAlexey Lapshin //
3f75da0c8SAlexey Lapshin // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4f75da0c8SAlexey Lapshin // See https://llvm.org/LICENSE.txt for license information.
5f75da0c8SAlexey Lapshin // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6f75da0c8SAlexey Lapshin //
7f75da0c8SAlexey Lapshin //===----------------------------------------------------------------------===//
8f75da0c8SAlexey Lapshin 
9f75da0c8SAlexey Lapshin #include "llvm/ObjCopy/ObjCopy.h"
10f75da0c8SAlexey Lapshin #include "llvm/ObjCopy/ConfigManager.h"
11f75da0c8SAlexey Lapshin #include "llvm/Object/ObjectFile.h"
12f75da0c8SAlexey Lapshin #include "llvm/ObjectYAML/yaml2obj.h"
13f75da0c8SAlexey Lapshin #include "llvm/Support/Error.h"
14f75da0c8SAlexey Lapshin #include "llvm/Support/FileUtilities.h"
15f75da0c8SAlexey Lapshin #include "llvm/Testing/Support/Error.h"
16f75da0c8SAlexey Lapshin #include "gtest/gtest.h"
17f75da0c8SAlexey Lapshin 
18f75da0c8SAlexey Lapshin using namespace llvm;
19f75da0c8SAlexey Lapshin using namespace object;
20f75da0c8SAlexey Lapshin using namespace objcopy;
21f75da0c8SAlexey Lapshin using namespace yaml;
22f75da0c8SAlexey Lapshin 
232dc4a80eSAlexey Lapshin const char *SimpleFileCOFFYAML = R"(
24f75da0c8SAlexey Lapshin --- !COFF
25f75da0c8SAlexey Lapshin header:
26f75da0c8SAlexey Lapshin   Machine:         IMAGE_FILE_MACHINE_AMD64
27f75da0c8SAlexey Lapshin   Characteristics: [  ]
28f75da0c8SAlexey Lapshin sections:
29f75da0c8SAlexey Lapshin   - Name:            .text
30f75da0c8SAlexey Lapshin     Characteristics: [  ]
31f75da0c8SAlexey Lapshin     Alignment:       4
32f75da0c8SAlexey Lapshin     SectionData:     E800000000C3C3C3
33f75da0c8SAlexey Lapshin symbols:
34f75da0c8SAlexey Lapshin ...
352dc4a80eSAlexey Lapshin )";
36f75da0c8SAlexey Lapshin 
372dc4a80eSAlexey Lapshin const char *SimpleFileELFYAML = R"(
38f75da0c8SAlexey Lapshin --- !ELF
39f75da0c8SAlexey Lapshin FileHeader:
40f75da0c8SAlexey Lapshin   Class:    ELFCLASS64
41f75da0c8SAlexey Lapshin   Data:     ELFDATA2LSB
422dc4a80eSAlexey Lapshin   Type:     ET_REL
432dc4a80eSAlexey Lapshin Sections:
44a6f3fedcSAlexey Lapshin   - Name:            .text
452dc4a80eSAlexey Lapshin     Type:            SHT_PROGBITS
462dc4a80eSAlexey Lapshin     Flags:           [ SHF_ALLOC ]
472dc4a80eSAlexey Lapshin     Content:        "12345678"
482dc4a80eSAlexey Lapshin )";
49a6f3fedcSAlexey Lapshin 
502dc4a80eSAlexey Lapshin const char *SimpleFileMachOYAML = R"(
51a6f3fedcSAlexey Lapshin --- !mach-o
52a6f3fedcSAlexey Lapshin FileHeader:
53a6f3fedcSAlexey Lapshin   magic:           0xFEEDFACF
54a6f3fedcSAlexey Lapshin   cputype:         0x01000007
55a6f3fedcSAlexey Lapshin   cpusubtype:      0x80000003
56a6f3fedcSAlexey Lapshin   filetype:        0x00000001
57a6f3fedcSAlexey Lapshin   ncmds:           1
58a6f3fedcSAlexey Lapshin   sizeofcmds:      152
59a6f3fedcSAlexey Lapshin   flags:           0x00002000
60a6f3fedcSAlexey Lapshin   reserved:        0x00000000
61a6f3fedcSAlexey Lapshin LoadCommands:
62a6f3fedcSAlexey Lapshin   - cmd:             LC_SEGMENT_64
63a6f3fedcSAlexey Lapshin     cmdsize:         152
64a6f3fedcSAlexey Lapshin     segname:         __TEXT
65a6f3fedcSAlexey Lapshin     vmaddr:          0
66a6f3fedcSAlexey Lapshin     vmsize:          4
67a6f3fedcSAlexey Lapshin     fileoff:         184
68a6f3fedcSAlexey Lapshin     filesize:        4
69a6f3fedcSAlexey Lapshin     maxprot:         7
70a6f3fedcSAlexey Lapshin     initprot:        7
71a6f3fedcSAlexey Lapshin     nsects:          1
72a6f3fedcSAlexey Lapshin     flags:           0
73a6f3fedcSAlexey Lapshin     Sections:
74a6f3fedcSAlexey Lapshin       - sectname:        __text
75a6f3fedcSAlexey Lapshin         segname:         __TEXT
76a6f3fedcSAlexey Lapshin         addr:            0x0000000000000000
77a6f3fedcSAlexey Lapshin         content:         'AABBCCDD'
78a6f3fedcSAlexey Lapshin         size:            4
79a6f3fedcSAlexey Lapshin         offset:          184
80a6f3fedcSAlexey Lapshin         align:           0
81a6f3fedcSAlexey Lapshin         reloff:          0x00000000
82a6f3fedcSAlexey Lapshin         nreloc:          0
83a6f3fedcSAlexey Lapshin         flags:           0x80000400
84a6f3fedcSAlexey Lapshin         reserved1:       0x00000000
85a6f3fedcSAlexey Lapshin         reserved2:       0x00000000
86a6f3fedcSAlexey Lapshin         reserved3:       0x00000000
87a6f3fedcSAlexey Lapshin ...
882dc4a80eSAlexey Lapshin )";
892dc4a80eSAlexey Lapshin 
902dc4a80eSAlexey Lapshin const char *SimpleFileWasmYAML = R"(
912dc4a80eSAlexey Lapshin --- !WASM
922dc4a80eSAlexey Lapshin FileHeader:
932dc4a80eSAlexey Lapshin   Version:         0x00000001
942dc4a80eSAlexey Lapshin Sections:
952dc4a80eSAlexey Lapshin   - Type: CUSTOM
962dc4a80eSAlexey Lapshin     Name: text
972dc4a80eSAlexey Lapshin     Payload: ABC123
982dc4a80eSAlexey Lapshin ...
992dc4a80eSAlexey Lapshin )";
1002dc4a80eSAlexey Lapshin 
1012dc4a80eSAlexey Lapshin // Create ObjectFile from \p YamlCreationString and do validation using \p
1022dc4a80eSAlexey Lapshin // IsValidFormat checker. \p Storage is a storage for data. \returns created
1032dc4a80eSAlexey Lapshin // ObjectFile.
createObjectFileFromYamlDescription(const char * YamlCreationString,SmallVector<char> & Storage,function_ref<bool (const Binary & File)> IsValidFormat)1042dc4a80eSAlexey Lapshin Expected<std::unique_ptr<ObjectFile>> createObjectFileFromYamlDescription(
1052dc4a80eSAlexey Lapshin     const char *YamlCreationString, SmallVector<char> &Storage,
1062dc4a80eSAlexey Lapshin     function_ref<bool(const Binary &File)> IsValidFormat) {
1072dc4a80eSAlexey Lapshin   auto ErrHandler = [&](const Twine &Msg) { FAIL() << "Error: " << Msg; };
1082dc4a80eSAlexey Lapshin 
1092dc4a80eSAlexey Lapshin   std::unique_ptr<ObjectFile> Obj =
1102dc4a80eSAlexey Lapshin       yaml2ObjectFile(Storage, YamlCreationString, ErrHandler);
1112dc4a80eSAlexey Lapshin   if (!Obj)
1122dc4a80eSAlexey Lapshin     return createError("could not create ObjectFile from yaml description");
1132dc4a80eSAlexey Lapshin 
1142dc4a80eSAlexey Lapshin   if (!IsValidFormat(*Obj))
1152dc4a80eSAlexey Lapshin     return createError("wrong file format");
1162dc4a80eSAlexey Lapshin 
117*dedf006fSAlexey Lapshin   return std::move(Obj);
1182dc4a80eSAlexey Lapshin }
1192dc4a80eSAlexey Lapshin 
1202dc4a80eSAlexey Lapshin // Call objcopy::executeObjcopyOnBinary for \p Config and \p In. \p DataVector
1212dc4a80eSAlexey Lapshin // is a holder for data. \returns Binary for copied data.
1222dc4a80eSAlexey Lapshin Expected<std::unique_ptr<Binary>>
callObjCopy(ConfigManager & Config,object::Binary & In,SmallVector<char> & DataVector,function_ref<bool (const Binary & File)> IsValidFormat)1232dc4a80eSAlexey Lapshin callObjCopy(ConfigManager &Config, object::Binary &In,
1242dc4a80eSAlexey Lapshin             SmallVector<char> &DataVector,
1252dc4a80eSAlexey Lapshin             function_ref<bool(const Binary &File)> IsValidFormat) {
1262dc4a80eSAlexey Lapshin   raw_svector_ostream OutStream(DataVector);
1272dc4a80eSAlexey Lapshin 
1282dc4a80eSAlexey Lapshin   if (Error Err = objcopy::executeObjcopyOnBinary(Config, In, OutStream))
1292dc4a80eSAlexey Lapshin     return std::move(Err);
1302dc4a80eSAlexey Lapshin 
1312dc4a80eSAlexey Lapshin   MemoryBufferRef Buffer(StringRef(DataVector.data(), DataVector.size()),
1322dc4a80eSAlexey Lapshin                          Config.Common.OutputFilename);
1332dc4a80eSAlexey Lapshin 
1342dc4a80eSAlexey Lapshin   Expected<std::unique_ptr<Binary>> Result = createBinary(Buffer);
1352dc4a80eSAlexey Lapshin 
1362dc4a80eSAlexey Lapshin   // Check copied file.
1372dc4a80eSAlexey Lapshin   if (!Result)
1382dc4a80eSAlexey Lapshin     return Result;
1392dc4a80eSAlexey Lapshin 
1402dc4a80eSAlexey Lapshin   if (!IsValidFormat(**Result))
1412dc4a80eSAlexey Lapshin     return createError("wrong file format");
1422dc4a80eSAlexey Lapshin 
1432dc4a80eSAlexey Lapshin   if (!(*Result)->isObject())
1442dc4a80eSAlexey Lapshin     return createError("binary is not object file");
1452dc4a80eSAlexey Lapshin 
1462dc4a80eSAlexey Lapshin   return Result;
1472dc4a80eSAlexey Lapshin }
1482dc4a80eSAlexey Lapshin 
1492dc4a80eSAlexey Lapshin // \returns true if specified \p File has a section named \p SectionName.
hasSection(ObjectFile & File,StringRef SectionName)1502dc4a80eSAlexey Lapshin bool hasSection(ObjectFile &File, StringRef SectionName) {
1512dc4a80eSAlexey Lapshin   for (const object::SectionRef &Sec : File.sections()) {
1522dc4a80eSAlexey Lapshin     Expected<StringRef> CurSecNameOrErr = Sec.getName();
1532dc4a80eSAlexey Lapshin     if (!CurSecNameOrErr)
1542dc4a80eSAlexey Lapshin       continue;
1552dc4a80eSAlexey Lapshin 
1562dc4a80eSAlexey Lapshin     if (*CurSecNameOrErr == SectionName)
1572dc4a80eSAlexey Lapshin       return true;
1582dc4a80eSAlexey Lapshin   }
1592dc4a80eSAlexey Lapshin 
1602dc4a80eSAlexey Lapshin   return false;
1612dc4a80eSAlexey Lapshin }
1622dc4a80eSAlexey Lapshin 
1632dc4a80eSAlexey Lapshin // Check that specified \p File has a section \p SectionName and its data
1642dc4a80eSAlexey Lapshin // matches \p SectionData.
checkSectionData(ObjectFile & File,StringRef SectionName,StringRef SectionData)1652dc4a80eSAlexey Lapshin void checkSectionData(ObjectFile &File, StringRef SectionName,
1662dc4a80eSAlexey Lapshin                       StringRef SectionData) {
1672dc4a80eSAlexey Lapshin   for (const object::SectionRef &Sec : File.sections()) {
1682dc4a80eSAlexey Lapshin     Expected<StringRef> CurSecNameOrErr = Sec.getName();
1692dc4a80eSAlexey Lapshin     ASSERT_THAT_EXPECTED(CurSecNameOrErr, Succeeded());
1702dc4a80eSAlexey Lapshin 
1712dc4a80eSAlexey Lapshin     if (*CurSecNameOrErr == SectionName) {
1722dc4a80eSAlexey Lapshin       Expected<StringRef> CurSectionData = Sec.getContents();
1732dc4a80eSAlexey Lapshin       ASSERT_THAT_EXPECTED(CurSectionData, Succeeded());
1742dc4a80eSAlexey Lapshin       EXPECT_TRUE(Sec.getSize() == SectionData.size());
1752dc4a80eSAlexey Lapshin       EXPECT_TRUE(memcmp(CurSectionData->data(), SectionData.data(),
1762dc4a80eSAlexey Lapshin                          SectionData.size()) == 0);
1772dc4a80eSAlexey Lapshin       return;
1782dc4a80eSAlexey Lapshin     }
1792dc4a80eSAlexey Lapshin   }
1802dc4a80eSAlexey Lapshin 
1812dc4a80eSAlexey Lapshin   // Section SectionName must be presented.
1822dc4a80eSAlexey Lapshin   EXPECT_TRUE(false);
1832dc4a80eSAlexey Lapshin }
1842dc4a80eSAlexey Lapshin 
copySimpleInMemoryFileImpl(const char * YamlCreationString,function_ref<bool (const Binary & File)> IsValidFormat)1852dc4a80eSAlexey Lapshin void copySimpleInMemoryFileImpl(
1862dc4a80eSAlexey Lapshin     const char *YamlCreationString,
1872dc4a80eSAlexey Lapshin     function_ref<bool(const Binary &File)> IsValidFormat) {
1882dc4a80eSAlexey Lapshin   SCOPED_TRACE("copySimpleInMemoryFileImpl");
1892dc4a80eSAlexey Lapshin 
1902dc4a80eSAlexey Lapshin   // Create Object file from YAML description.
1912dc4a80eSAlexey Lapshin   SmallVector<char> Storage;
1922dc4a80eSAlexey Lapshin   Expected<std::unique_ptr<ObjectFile>> Obj =
1932dc4a80eSAlexey Lapshin       createObjectFileFromYamlDescription(YamlCreationString, Storage,
1942dc4a80eSAlexey Lapshin                                           IsValidFormat);
1952dc4a80eSAlexey Lapshin   ASSERT_THAT_EXPECTED(Obj, Succeeded());
1962dc4a80eSAlexey Lapshin 
1972dc4a80eSAlexey Lapshin   ConfigManager Config;
1982dc4a80eSAlexey Lapshin   Config.Common.OutputFilename = "a.out";
1992dc4a80eSAlexey Lapshin 
2002dc4a80eSAlexey Lapshin   // Call executeObjcopyOnBinary()
2012dc4a80eSAlexey Lapshin   SmallVector<char> DataVector;
2022dc4a80eSAlexey Lapshin   Expected<std::unique_ptr<Binary>> Result =
2032dc4a80eSAlexey Lapshin       callObjCopy(Config, *Obj.get(), DataVector, IsValidFormat);
2042dc4a80eSAlexey Lapshin   ASSERT_THAT_EXPECTED(Result, Succeeded());
2052dc4a80eSAlexey Lapshin }
2062dc4a80eSAlexey Lapshin 
TEST(CopySimpleInMemoryFile,COFF)2072dc4a80eSAlexey Lapshin TEST(CopySimpleInMemoryFile, COFF) {
2082dc4a80eSAlexey Lapshin   SCOPED_TRACE("CopySimpleInMemoryFileCOFF");
2092dc4a80eSAlexey Lapshin 
2102dc4a80eSAlexey Lapshin   copySimpleInMemoryFileImpl(SimpleFileCOFFYAML,
2112dc4a80eSAlexey Lapshin                              [](const Binary &File) { return File.isCOFF(); });
2122dc4a80eSAlexey Lapshin }
2132dc4a80eSAlexey Lapshin 
TEST(CopySimpleInMemoryFile,ELF)2142dc4a80eSAlexey Lapshin TEST(CopySimpleInMemoryFile, ELF) {
2152dc4a80eSAlexey Lapshin   SCOPED_TRACE("CopySimpleInMemoryFileELF");
2162dc4a80eSAlexey Lapshin 
2172dc4a80eSAlexey Lapshin   copySimpleInMemoryFileImpl(SimpleFileELFYAML,
2182dc4a80eSAlexey Lapshin                              [](const Binary &File) { return File.isELF(); });
2192dc4a80eSAlexey Lapshin }
2202dc4a80eSAlexey Lapshin 
TEST(CopySimpleInMemoryFile,MachO)2212dc4a80eSAlexey Lapshin TEST(CopySimpleInMemoryFile, MachO) {
2222dc4a80eSAlexey Lapshin   SCOPED_TRACE("CopySimpleInMemoryFileMachO");
2232dc4a80eSAlexey Lapshin 
2242dc4a80eSAlexey Lapshin   copySimpleInMemoryFileImpl(SimpleFileMachOYAML,
2252dc4a80eSAlexey Lapshin                              [](const Binary &File) { return File.isMachO(); });
2262dc4a80eSAlexey Lapshin }
2272dc4a80eSAlexey Lapshin 
TEST(CopySimpleInMemoryFile,Wasm)2282dc4a80eSAlexey Lapshin TEST(CopySimpleInMemoryFile, Wasm) {
2292dc4a80eSAlexey Lapshin   SCOPED_TRACE("CopySimpleInMemoryFileWasm");
2302dc4a80eSAlexey Lapshin 
2312dc4a80eSAlexey Lapshin   copySimpleInMemoryFileImpl(SimpleFileWasmYAML,
2322dc4a80eSAlexey Lapshin                              [](const Binary &File) { return File.isWasm(); });
2332dc4a80eSAlexey Lapshin }
2342dc4a80eSAlexey Lapshin 
2352dc4a80eSAlexey Lapshin enum Action : uint8_t { AddSection, UpdateSection };
2362dc4a80eSAlexey Lapshin 
addOrUpdateSectionToFileImpl(const char * YamlCreationString,function_ref<bool (const Binary & File)> IsValidFormat,StringRef NewSectionName,StringRef NewSectionData,Action SectionAction)2372dc4a80eSAlexey Lapshin void addOrUpdateSectionToFileImpl(
2382dc4a80eSAlexey Lapshin     const char *YamlCreationString,
2392dc4a80eSAlexey Lapshin     function_ref<bool(const Binary &File)> IsValidFormat,
2402dc4a80eSAlexey Lapshin     StringRef NewSectionName, StringRef NewSectionData, Action SectionAction) {
2412dc4a80eSAlexey Lapshin   SCOPED_TRACE("addOrUpdateSectionToFileImpl");
2422dc4a80eSAlexey Lapshin 
2432dc4a80eSAlexey Lapshin   // Create Object file from YAML description.
2442dc4a80eSAlexey Lapshin   SmallVector<char> Storage;
2452dc4a80eSAlexey Lapshin   Expected<std::unique_ptr<ObjectFile>> Obj =
2462dc4a80eSAlexey Lapshin       createObjectFileFromYamlDescription(YamlCreationString, Storage,
2472dc4a80eSAlexey Lapshin                                           IsValidFormat);
2482dc4a80eSAlexey Lapshin   ASSERT_THAT_EXPECTED(Obj, Succeeded());
2492dc4a80eSAlexey Lapshin 
2502dc4a80eSAlexey Lapshin   std::unique_ptr<MemoryBuffer> NewSectionBuffer =
2512dc4a80eSAlexey Lapshin       MemoryBuffer::getMemBuffer(NewSectionData, NewSectionName, false);
2522dc4a80eSAlexey Lapshin   std::string Name;
2532dc4a80eSAlexey Lapshin   if ((*Obj)->isMachO())
2542dc4a80eSAlexey Lapshin     Name = "__TEXT," + NewSectionName.str();
2552dc4a80eSAlexey Lapshin   else
2562dc4a80eSAlexey Lapshin     Name = NewSectionName.str();
2572dc4a80eSAlexey Lapshin 
2582dc4a80eSAlexey Lapshin   ConfigManager Config;
2592dc4a80eSAlexey Lapshin   Config.Common.OutputFilename = "a.out";
2602dc4a80eSAlexey Lapshin   if (SectionAction == AddSection)
2612dc4a80eSAlexey Lapshin     Config.Common.AddSection.push_back({Name, std::move(NewSectionBuffer)});
2622dc4a80eSAlexey Lapshin   else
2632dc4a80eSAlexey Lapshin     Config.Common.UpdateSection.push_back({Name, std::move(NewSectionBuffer)});
2642dc4a80eSAlexey Lapshin 
2652dc4a80eSAlexey Lapshin   // Call executeObjcopyOnBinary()
2662dc4a80eSAlexey Lapshin   SmallVector<char> DataVector;
2672dc4a80eSAlexey Lapshin   Expected<std::unique_ptr<Binary>> Result =
2682dc4a80eSAlexey Lapshin       callObjCopy(Config, *Obj.get(), DataVector, IsValidFormat);
2692dc4a80eSAlexey Lapshin   ASSERT_THAT_EXPECTED(Result, Succeeded());
2702dc4a80eSAlexey Lapshin 
2712dc4a80eSAlexey Lapshin   // Check that copied file has the new section.
2722dc4a80eSAlexey Lapshin   checkSectionData(*static_cast<ObjectFile *>((*Result).get()), NewSectionName,
2732dc4a80eSAlexey Lapshin                    NewSectionData);
2742dc4a80eSAlexey Lapshin }
2752dc4a80eSAlexey Lapshin 
TEST(AddSection,COFF)2762dc4a80eSAlexey Lapshin TEST(AddSection, COFF) {
2772dc4a80eSAlexey Lapshin   SCOPED_TRACE("addSectionToFileCOFF");
2782dc4a80eSAlexey Lapshin 
2792dc4a80eSAlexey Lapshin   addOrUpdateSectionToFileImpl(
2802dc4a80eSAlexey Lapshin       SimpleFileCOFFYAML, [](const Binary &File) { return File.isCOFF(); },
2812dc4a80eSAlexey Lapshin       ".foo", "1234", AddSection);
2822dc4a80eSAlexey Lapshin }
2832dc4a80eSAlexey Lapshin 
TEST(AddSection,ELF)2842dc4a80eSAlexey Lapshin TEST(AddSection, ELF) {
2852dc4a80eSAlexey Lapshin   SCOPED_TRACE("addSectionToFileELF");
2862dc4a80eSAlexey Lapshin 
2872dc4a80eSAlexey Lapshin   addOrUpdateSectionToFileImpl(
2882dc4a80eSAlexey Lapshin       SimpleFileELFYAML, [](const Binary &File) { return File.isELF(); },
2892dc4a80eSAlexey Lapshin       ".foo", "1234", AddSection);
2902dc4a80eSAlexey Lapshin }
2912dc4a80eSAlexey Lapshin 
TEST(AddSection,MachO)2922dc4a80eSAlexey Lapshin TEST(AddSection, MachO) {
2932dc4a80eSAlexey Lapshin   SCOPED_TRACE("addSectionToFileMachO");
2942dc4a80eSAlexey Lapshin 
2952dc4a80eSAlexey Lapshin   addOrUpdateSectionToFileImpl(
2962dc4a80eSAlexey Lapshin       SimpleFileMachOYAML, [](const Binary &File) { return File.isMachO(); },
2972dc4a80eSAlexey Lapshin       "__foo", "1234", AddSection);
298a6f3fedcSAlexey Lapshin }
299a6f3fedcSAlexey Lapshin 
TEST(AddSection,Wasm)300a6f3fedcSAlexey Lapshin TEST(AddSection, Wasm) {
301a6f3fedcSAlexey Lapshin   SCOPED_TRACE("addSectionToFileWasm");
302a6f3fedcSAlexey Lapshin 
303a6f3fedcSAlexey Lapshin   addOrUpdateSectionToFileImpl(
3042dc4a80eSAlexey Lapshin       SimpleFileWasmYAML, [](const Binary &File) { return File.isWasm(); },
3052dc4a80eSAlexey Lapshin       ".foo", "1234", AddSection);
306a6f3fedcSAlexey Lapshin }
307a6f3fedcSAlexey Lapshin 
TEST(UpdateSection,COFF)308a6f3fedcSAlexey Lapshin TEST(UpdateSection, COFF) {
309a6f3fedcSAlexey Lapshin   SCOPED_TRACE("updateSectionToFileCOFF");
310a6f3fedcSAlexey Lapshin 
311a6f3fedcSAlexey Lapshin   addOrUpdateSectionToFileImpl(
3122dc4a80eSAlexey Lapshin       SimpleFileCOFFYAML, [](const Binary &File) { return File.isCOFF(); },
3132dc4a80eSAlexey Lapshin       ".text", "1234", UpdateSection);
314a6f3fedcSAlexey Lapshin }
315a6f3fedcSAlexey Lapshin 
TEST(UpdateSection,ELF)316a6f3fedcSAlexey Lapshin TEST(UpdateSection, ELF) {
317a6f3fedcSAlexey Lapshin   SCOPED_TRACE("updateSectionToFileELF");
318a6f3fedcSAlexey Lapshin 
319a6f3fedcSAlexey Lapshin   addOrUpdateSectionToFileImpl(
3202dc4a80eSAlexey Lapshin       SimpleFileELFYAML, [](const Binary &File) { return File.isELF(); },
3212dc4a80eSAlexey Lapshin       ".text", "1234", UpdateSection);
322a6f3fedcSAlexey Lapshin }
323a6f3fedcSAlexey Lapshin 
TEST(UpdateSection,MachO)324a6f3fedcSAlexey Lapshin TEST(UpdateSection, MachO) {
325a6f3fedcSAlexey Lapshin   SCOPED_TRACE("updateSectionToFileMachO");
326a6f3fedcSAlexey Lapshin 
327a6f3fedcSAlexey Lapshin   addOrUpdateSectionToFileImpl(
3282dc4a80eSAlexey Lapshin       SimpleFileMachOYAML, [](const Binary &File) { return File.isMachO(); },
3292dc4a80eSAlexey Lapshin       "__text", "1234", UpdateSection);
3302dc4a80eSAlexey Lapshin }
3312dc4a80eSAlexey Lapshin 
removeSectionByPatternImpl(const char * YamlCreationString,function_ref<bool (const Binary & File)> IsValidFormat,StringRef SectionWildcard,StringRef SectionName)3322dc4a80eSAlexey Lapshin void removeSectionByPatternImpl(
3332dc4a80eSAlexey Lapshin     const char *YamlCreationString,
3342dc4a80eSAlexey Lapshin     function_ref<bool(const Binary &File)> IsValidFormat,
3352dc4a80eSAlexey Lapshin     StringRef SectionWildcard, StringRef SectionName) {
3362dc4a80eSAlexey Lapshin   SCOPED_TRACE("removeSectionByPatternImpl");
3372dc4a80eSAlexey Lapshin 
3382dc4a80eSAlexey Lapshin   // Create Object file from YAML description.
3392dc4a80eSAlexey Lapshin   SmallVector<char> Storage;
3402dc4a80eSAlexey Lapshin   Expected<std::unique_ptr<ObjectFile>> Obj =
3412dc4a80eSAlexey Lapshin       createObjectFileFromYamlDescription(YamlCreationString, Storage,
3422dc4a80eSAlexey Lapshin                                           IsValidFormat);
3432dc4a80eSAlexey Lapshin   ASSERT_THAT_EXPECTED(Obj, Succeeded());
3442dc4a80eSAlexey Lapshin 
3452dc4a80eSAlexey Lapshin   // Check that section is present.
3462dc4a80eSAlexey Lapshin   EXPECT_TRUE(hasSection(**Obj, SectionName));
3472dc4a80eSAlexey Lapshin 
3482dc4a80eSAlexey Lapshin   Expected<NameOrPattern> Pattern = objcopy::NameOrPattern::create(
3492dc4a80eSAlexey Lapshin       SectionWildcard, objcopy::MatchStyle::Wildcard,
3502dc4a80eSAlexey Lapshin       [](Error Err) { return Err; });
3512dc4a80eSAlexey Lapshin 
3522dc4a80eSAlexey Lapshin   ConfigManager Config;
3532dc4a80eSAlexey Lapshin   Config.Common.OutputFilename = "a.out";
3542dc4a80eSAlexey Lapshin   EXPECT_THAT_ERROR(Config.Common.ToRemove.addMatcher(std::move(Pattern)),
3552dc4a80eSAlexey Lapshin                     Succeeded());
3562dc4a80eSAlexey Lapshin 
3572dc4a80eSAlexey Lapshin   SmallVector<char> DataVector;
3582dc4a80eSAlexey Lapshin   Expected<std::unique_ptr<Binary>> Result =
3592dc4a80eSAlexey Lapshin       callObjCopy(Config, *Obj.get(), DataVector, IsValidFormat);
3602dc4a80eSAlexey Lapshin   ASSERT_THAT_EXPECTED(Result, Succeeded());
3612dc4a80eSAlexey Lapshin 
3622dc4a80eSAlexey Lapshin   // Check that section was removed.
3632dc4a80eSAlexey Lapshin   EXPECT_FALSE(
3642dc4a80eSAlexey Lapshin       hasSection(*static_cast<ObjectFile *>((*Result).get()), SectionName));
3652dc4a80eSAlexey Lapshin }
3662dc4a80eSAlexey Lapshin 
TEST(RemoveSectionByPattern,COFF)3672dc4a80eSAlexey Lapshin TEST(RemoveSectionByPattern, COFF) {
3682dc4a80eSAlexey Lapshin   SCOPED_TRACE("removeSectionByPatternCOFF");
3692dc4a80eSAlexey Lapshin 
3702dc4a80eSAlexey Lapshin   removeSectionByPatternImpl(
3712dc4a80eSAlexey Lapshin       SimpleFileCOFFYAML, [](const Binary &File) { return File.isCOFF(); },
3722dc4a80eSAlexey Lapshin       "\\.text*", ".text");
3732dc4a80eSAlexey Lapshin }
3742dc4a80eSAlexey Lapshin 
TEST(RemoveSectionByPattern,ELF)3752dc4a80eSAlexey Lapshin TEST(RemoveSectionByPattern, ELF) {
3762dc4a80eSAlexey Lapshin   SCOPED_TRACE("removeSectionByPatternELF");
3772dc4a80eSAlexey Lapshin 
3782dc4a80eSAlexey Lapshin   removeSectionByPatternImpl(
3792dc4a80eSAlexey Lapshin       SimpleFileELFYAML, [](const Binary &File) { return File.isELF(); },
3802dc4a80eSAlexey Lapshin       "\\.text*", ".text");
3812dc4a80eSAlexey Lapshin }
3822dc4a80eSAlexey Lapshin 
TEST(RemoveSectionByPattern,MachO)3832dc4a80eSAlexey Lapshin TEST(RemoveSectionByPattern, MachO) {
3842dc4a80eSAlexey Lapshin   SCOPED_TRACE("removeSectionByPatternMachO");
3852dc4a80eSAlexey Lapshin 
3862dc4a80eSAlexey Lapshin   removeSectionByPatternImpl(
3872dc4a80eSAlexey Lapshin       SimpleFileMachOYAML, [](const Binary &File) { return File.isMachO(); },
3882dc4a80eSAlexey Lapshin       "__TEXT,__text*", "__text");
3892dc4a80eSAlexey Lapshin }
3902dc4a80eSAlexey Lapshin 
TEST(RemoveSectionByPattern,Wasm)3912dc4a80eSAlexey Lapshin TEST(RemoveSectionByPattern, Wasm) {
3922dc4a80eSAlexey Lapshin   SCOPED_TRACE("removeSectionByPatternWasm");
3932dc4a80eSAlexey Lapshin 
3942dc4a80eSAlexey Lapshin   removeSectionByPatternImpl(
3952dc4a80eSAlexey Lapshin       SimpleFileWasmYAML, [](const Binary &File) { return File.isWasm(); },
3962dc4a80eSAlexey Lapshin       "text*", "text");
397a6f3fedcSAlexey Lapshin }
398