mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2024-12-15 12:09:51 +00:00
[yaml2obj/obj2yaml][MachO] Allow setting custom section data
Reviewers: alexshap, jhenderson, rupprecht Reviewed By: alexshap, jhenderson Subscribers: abrachet, hiraditya, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D65799 llvm-svn: 369348
This commit is contained in:
parent
9c371309f3
commit
522377494b
@ -581,6 +581,11 @@ struct section_64 {
|
||||
uint32_t reserved3;
|
||||
};
|
||||
|
||||
inline bool isVirtualSection(uint8_t type) {
|
||||
return (type == MachO::S_ZEROFILL || type == MachO::S_GB_ZEROFILL ||
|
||||
type == MachO::S_THREAD_LOCAL_ZEROFILL);
|
||||
}
|
||||
|
||||
struct fvmlib {
|
||||
uint32_t name;
|
||||
uint32_t minor_version;
|
||||
|
@ -297,6 +297,7 @@ public:
|
||||
uint64_t getSectionAddress(DataRefImpl Sec) const override;
|
||||
uint64_t getSectionIndex(DataRefImpl Sec) const override;
|
||||
uint64_t getSectionSize(DataRefImpl Sec) const override;
|
||||
ArrayRef<uint8_t> getSectionContents(uint32_t Offset, uint64_t Size) const;
|
||||
Expected<ArrayRef<uint8_t>>
|
||||
getSectionContents(DataRefImpl Sec) const override;
|
||||
uint64_t getSectionAlignment(DataRefImpl Sec) const override;
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/BinaryFormat/MachO.h"
|
||||
#include "llvm/ObjectYAML/DWARFYAML.h"
|
||||
#include "llvm/ObjectYAML/YAML.h"
|
||||
#include "llvm/Support/YAMLTraits.h"
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
@ -39,6 +40,7 @@ struct Section {
|
||||
llvm::yaml::Hex32 reserved1;
|
||||
llvm::yaml::Hex32 reserved2;
|
||||
llvm::yaml::Hex32 reserved3;
|
||||
Optional<llvm::yaml::BinaryRef> content;
|
||||
};
|
||||
|
||||
struct FileHeader {
|
||||
@ -198,6 +200,7 @@ template <> struct MappingTraits<MachOYAML::ExportEntry> {
|
||||
|
||||
template <> struct MappingTraits<MachOYAML::Section> {
|
||||
static void mapping(IO &IO, MachOYAML::Section &Section);
|
||||
static StringRef validate(IO &io, MachOYAML::Section &Section);
|
||||
};
|
||||
|
||||
template <> struct MappingTraits<MachOYAML::NListEntry> {
|
||||
|
@ -1945,6 +1945,11 @@ uint64_t MachOObjectFile::getSectionSize(DataRefImpl Sec) const {
|
||||
return SectSize;
|
||||
}
|
||||
|
||||
ArrayRef<uint8_t> MachOObjectFile::getSectionContents(uint32_t Offset,
|
||||
uint64_t Size) const {
|
||||
return arrayRefFromStringRef(getData().substr(Offset, Size));
|
||||
}
|
||||
|
||||
Expected<ArrayRef<uint8_t>>
|
||||
MachOObjectFile::getSectionContents(DataRefImpl Sec) const {
|
||||
uint32_t Offset;
|
||||
@ -1960,7 +1965,7 @@ MachOObjectFile::getSectionContents(DataRefImpl Sec) const {
|
||||
Size = Sect.size;
|
||||
}
|
||||
|
||||
return arrayRefFromStringRef(getData().substr(Offset, Size));
|
||||
return getSectionContents(Offset, Size);
|
||||
}
|
||||
|
||||
uint64_t MachOObjectFile::getSectionAlignment(DataRefImpl Sec) const {
|
||||
|
@ -262,11 +262,6 @@ Error MachOWriter::writeLoadCommands(raw_ostream &OS) {
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
static bool isVirtualSection(uint8_t type) {
|
||||
return (type == MachO::S_ZEROFILL || type == MachO::S_GB_ZEROFILL ||
|
||||
type == MachO::S_THREAD_LOCAL_ZEROFILL);
|
||||
}
|
||||
|
||||
Error MachOWriter::writeSectionData(raw_ostream &OS) {
|
||||
bool FoundLinkEditSeg = false;
|
||||
for (auto &LC : Obj.LoadCommands) {
|
||||
@ -311,11 +306,17 @@ Error MachOWriter::writeSectionData(raw_ostream &OS) {
|
||||
}
|
||||
|
||||
// Skip if it's a virtual section.
|
||||
if (isVirtualSection(Sec.flags & MachO::SECTION_TYPE))
|
||||
if (MachO::isVirtualSection(Sec.flags & MachO::SECTION_TYPE))
|
||||
continue;
|
||||
|
||||
// Fill section data with 0xDEADBEEF
|
||||
Fill(OS, Sec.size, 0xDEADBEEFu);
|
||||
if (Sec.content) {
|
||||
yaml::BinaryRef Content = *Sec.content;
|
||||
Content.writeAsBinary(OS);
|
||||
ZeroFillBytes(OS, Sec.size - Content.binary_size());
|
||||
} else {
|
||||
// Fill section data with 0xDEADBEEF.
|
||||
Fill(OS, Sec.size, 0xDEADBEEFu);
|
||||
}
|
||||
}
|
||||
uint64_t segSize = is64Bit ? LC.Data.segment_command_64_data.filesize
|
||||
: LC.Data.segment_command_data.filesize;
|
||||
|
@ -287,6 +287,15 @@ void MappingTraits<MachOYAML::Section>::mapping(IO &IO,
|
||||
IO.mapRequired("reserved1", Section.reserved1);
|
||||
IO.mapRequired("reserved2", Section.reserved2);
|
||||
IO.mapOptional("reserved3", Section.reserved3);
|
||||
IO.mapOptional("content", Section.content);
|
||||
}
|
||||
|
||||
StringRef
|
||||
MappingTraits<MachOYAML::Section>::validate(IO &IO,
|
||||
MachOYAML::Section &Section) {
|
||||
if (Section.content && Section.size < Section.content->binary_size())
|
||||
return "Section size must be greater than or equal to the content size";
|
||||
return {};
|
||||
}
|
||||
|
||||
void MappingTraits<MachO::build_tool_version>::mapping(
|
||||
|
161
llvm/test/ObjectYAML/MachO/section_data.yaml
Normal file
161
llvm/test/ObjectYAML/MachO/section_data.yaml
Normal file
@ -0,0 +1,161 @@
|
||||
## Show that yaml2obj supports custom section data for Mach-O YAML inputs.
|
||||
|
||||
## Case 1: The size of content is greater than the section size.
|
||||
# RUN: not yaml2obj --docnum=1 %s -o %t1 2>&1 | FileCheck %s --check-prefix=CASE1
|
||||
# CASE1: error: Section size must be greater than or equal to the content size
|
||||
|
||||
--- !mach-o
|
||||
FileHeader:
|
||||
magic: 0xFEEDFACF
|
||||
cputype: 0x01000007
|
||||
cpusubtype: 0x00000003
|
||||
filetype: 0x00000001
|
||||
ncmds: 1
|
||||
sizeofcmds: 232
|
||||
flags: 0x00002000
|
||||
reserved: 0x00000000
|
||||
LoadCommands:
|
||||
- cmd: LC_SEGMENT_64
|
||||
cmdsize: 232
|
||||
segname: ''
|
||||
vmaddr: 0
|
||||
vmsize: 4
|
||||
fileoff: 392
|
||||
filesize: 4
|
||||
maxprot: 7
|
||||
initprot: 7
|
||||
nsects: 1
|
||||
flags: 0
|
||||
Sections:
|
||||
- sectname: __data
|
||||
segname: __DATA
|
||||
addr: 0x0000000000000000
|
||||
size: 0
|
||||
offset: 0x00000188
|
||||
align: 2
|
||||
reloff: 0x00000000
|
||||
nreloc: 0
|
||||
flags: 0x00000000
|
||||
reserved1: 0x00000000
|
||||
reserved2: 0x00000000
|
||||
reserved3: 0x00000000
|
||||
content: CDAB3412
|
||||
|
||||
## Case 2: The content size equals the section size.
|
||||
# RUN: yaml2obj --docnum=2 %s > %t2
|
||||
# RUN: llvm-readobj --sections --section-data %t2 | FileCheck %s --check-prefix=CASE2
|
||||
# CASE2: Index: 0
|
||||
# CASE2-NEXT: Name: __data (5F 5F 64 61 74 61 00 00 00 00 00 00 00 00 00 00)
|
||||
# CASE2-NEXT: Segment: __DATA (5F 5F 44 41 54 41 00 00 00 00 00 00 00 00 00 00)
|
||||
# CASE2-NEXT: Address: 0x0
|
||||
# CASE2-NEXT: Size: 0x4
|
||||
# CASE2-NEXT: Offset: 392
|
||||
# CASE2-NEXT: Alignment: 2
|
||||
# CASE2-NEXT: RelocationOffset: 0x0
|
||||
# CASE2-NEXT: RelocationCount: 0
|
||||
# CASE2-NEXT: Type: Regular (0x0)
|
||||
# CASE2-NEXT: Attributes [ (0x0)
|
||||
# CASE2-NEXT: ]
|
||||
# CASE2-NEXT: Reserved1: 0x0
|
||||
# CASE2-NEXT: Reserved2: 0x0
|
||||
# CASE2-NEXT: Reserved3: 0x0
|
||||
# CASE2-NEXT: SectionData (
|
||||
# CASE2-NEXT: 0000: CDAB3412 |..4.|
|
||||
# CASE2-NEXT: )
|
||||
|
||||
--- !mach-o
|
||||
FileHeader:
|
||||
magic: 0xFEEDFACF
|
||||
cputype: 0x01000007
|
||||
cpusubtype: 0x00000003
|
||||
filetype: 0x00000001
|
||||
ncmds: 1
|
||||
sizeofcmds: 232
|
||||
flags: 0x00002000
|
||||
reserved: 0x00000000
|
||||
LoadCommands:
|
||||
- cmd: LC_SEGMENT_64
|
||||
cmdsize: 232
|
||||
segname: ''
|
||||
vmaddr: 0
|
||||
vmsize: 4
|
||||
fileoff: 392
|
||||
filesize: 4
|
||||
maxprot: 7
|
||||
initprot: 7
|
||||
nsects: 1
|
||||
flags: 0
|
||||
Sections:
|
||||
- sectname: __data
|
||||
segname: __DATA
|
||||
addr: 0x0000000000000000
|
||||
size: 4
|
||||
offset: 0x00000188
|
||||
align: 2
|
||||
reloff: 0x00000000
|
||||
nreloc: 0
|
||||
flags: 0x00000000
|
||||
reserved1: 0x00000000
|
||||
reserved2: 0x00000000
|
||||
reserved3: 0x00000000
|
||||
content: CDAB3412
|
||||
|
||||
## Case 3: The content size is less than the section size. In this case, the area
|
||||
## after the custom content is filled with zeroes.
|
||||
# RUN: yaml2obj --docnum=3 %s > %t3
|
||||
# RUN: llvm-readobj --sections --section-data %t3 | FileCheck %s --check-prefix=CASE3
|
||||
# CASE3: Index: 0
|
||||
# CASE3-NEXT: Name: __data (5F 5F 64 61 74 61 00 00 00 00 00 00 00 00 00 00)
|
||||
# CASE3-NEXT: Segment: __DATA (5F 5F 44 41 54 41 00 00 00 00 00 00 00 00 00 00)
|
||||
# CASE3-NEXT: Address: 0x0
|
||||
# CASE3-NEXT: Size: 0x4
|
||||
# CASE3-NEXT: Offset: 392
|
||||
# CASE3-NEXT: Alignment: 2
|
||||
# CASE3-NEXT: RelocationOffset: 0x0
|
||||
# CASE3-NEXT: RelocationCount: 0
|
||||
# CASE3-NEXT: Type: Regular (0x0)
|
||||
# CASE3-NEXT: Attributes [ (0x0)
|
||||
# CASE3-NEXT: ]
|
||||
# CASE3-NEXT: Reserved1: 0x0
|
||||
# CASE3-NEXT: Reserved2: 0x0
|
||||
# CASE3-NEXT: Reserved3: 0x0
|
||||
# CASE3-NEXT: SectionData (
|
||||
# CASE3-NEXT: 0000: AA000000 |....|
|
||||
# CASE3-NEXT: )
|
||||
|
||||
--- !mach-o
|
||||
FileHeader:
|
||||
magic: 0xFEEDFACF
|
||||
cputype: 0x01000007
|
||||
cpusubtype: 0x00000003
|
||||
filetype: 0x00000001
|
||||
ncmds: 1
|
||||
sizeofcmds: 232
|
||||
flags: 0x00002000
|
||||
reserved: 0x00000000
|
||||
LoadCommands:
|
||||
- cmd: LC_SEGMENT_64
|
||||
cmdsize: 232
|
||||
segname: ''
|
||||
vmaddr: 0
|
||||
vmsize: 4
|
||||
fileoff: 392
|
||||
filesize: 4
|
||||
maxprot: 7
|
||||
initprot: 7
|
||||
nsects: 1
|
||||
flags: 0
|
||||
Sections:
|
||||
- sectname: __data
|
||||
segname: __DATA
|
||||
addr: 0x0000000000000000
|
||||
size: 4
|
||||
offset: 0x00000188
|
||||
align: 2
|
||||
reloff: 0x00000000
|
||||
nreloc: 0
|
||||
flags: 0x00000000
|
||||
reserved1: 0x00000000
|
||||
reserved2: 0x00000000
|
||||
reserved3: 0x00000000
|
||||
content: AA
|
@ -163,8 +163,7 @@ LinkEditData:
|
||||
- ''
|
||||
...
|
||||
|
||||
# CHECK: Sections:
|
||||
# CHECK-NEXT: - sectname: __text
|
||||
# CHECK: - sectname: __text
|
||||
# CHECK-NEXT: segname: __TEXT
|
||||
# CHECK-NEXT: addr: 0x0000000000000000
|
||||
# CHECK-NEXT: size: 72
|
||||
@ -176,6 +175,7 @@ LinkEditData:
|
||||
# CHECK-NEXT: reserved1: 0x00000000
|
||||
# CHECK-NEXT: reserved2: 0x00000000
|
||||
# CHECK-NEXT: reserved3: 0x00000000
|
||||
# CHECK-NEXT: content: {{(EFBEADDE){18}$}}
|
||||
# CHECK-NEXT: - sectname: __data
|
||||
# CHECK-NEXT: segname: __DATA
|
||||
# CHECK-NEXT: addr: 0x0000000000000048
|
||||
@ -188,6 +188,7 @@ LinkEditData:
|
||||
# CHECK-NEXT: reserved1: 0x00000000
|
||||
# CHECK-NEXT: reserved2: 0x00000000
|
||||
# CHECK-NEXT: reserved3: 0x00000000
|
||||
# CHECK-NEXT: content: EFBEADDE{{$}}
|
||||
# CHECK-NEXT: - sectname: __bss
|
||||
# CHECK-NEXT: segname: __DATA
|
||||
# CHECK-NEXT: addr: 0x00000000000000A0
|
||||
@ -224,3 +225,4 @@ LinkEditData:
|
||||
# CHECK-NEXT: reserved1: 0x00000000
|
||||
# CHECK-NEXT: reserved2: 0x00000000
|
||||
# CHECK-NEXT: reserved3: 0x00000000
|
||||
# CHECK-NEXT: content: {{.*}}
|
||||
|
@ -39,6 +39,15 @@ class MachODumper {
|
||||
void dumpDebugStrings(DWARFContext &DCtx,
|
||||
std::unique_ptr<MachOYAML::Object> &Y);
|
||||
|
||||
template <typename SectionType>
|
||||
MachOYAML::Section constructSectionCommon(SectionType Sec);
|
||||
template <typename SectionType>
|
||||
MachOYAML::Section constructSection(SectionType Sec);
|
||||
template <typename SectionType, typename SegmentType>
|
||||
const char *
|
||||
extractSections(const llvm::object::MachOObjectFile::LoadCommandInfo &LoadCmd,
|
||||
std::vector<MachOYAML::Section> &Sections);
|
||||
|
||||
public:
|
||||
MachODumper(const object::MachOObjectFile &O) : Obj(O) {}
|
||||
Expected<std::unique_ptr<MachOYAML::Object>> dump();
|
||||
@ -46,7 +55,7 @@ public:
|
||||
|
||||
#define HANDLE_LOAD_COMMAND(LCName, LCValue, LCStruct) \
|
||||
case MachO::LCName: \
|
||||
memcpy((void *) & (LC.Data.LCStruct##_data), LoadCmd.Ptr, \
|
||||
memcpy((void *)&(LC.Data.LCStruct##_data), LoadCmd.Ptr, \
|
||||
sizeof(MachO::LCStruct)); \
|
||||
if (Obj.isLittleEndian() != sys::IsLittleEndianHost) \
|
||||
MachO::swapStruct(LC.Data.LCStruct##_data); \
|
||||
@ -54,7 +63,7 @@ public:
|
||||
break;
|
||||
|
||||
template <typename SectionType>
|
||||
MachOYAML::Section constructSectionCommon(SectionType Sec) {
|
||||
MachOYAML::Section MachODumper::constructSectionCommon(SectionType Sec) {
|
||||
MachOYAML::Section TempSec;
|
||||
memcpy(reinterpret_cast<void *>(&TempSec.sectname[0]), &Sec.sectname[0], 16);
|
||||
memcpy(reinterpret_cast<void *>(&TempSec.segname[0]), &Sec.segname[0], 16);
|
||||
@ -68,34 +77,35 @@ MachOYAML::Section constructSectionCommon(SectionType Sec) {
|
||||
TempSec.reserved1 = Sec.reserved1;
|
||||
TempSec.reserved2 = Sec.reserved2;
|
||||
TempSec.reserved3 = 0;
|
||||
if (!MachO::isVirtualSection(Sec.flags & MachO::SECTION_TYPE))
|
||||
TempSec.content =
|
||||
yaml::BinaryRef(Obj.getSectionContents(Sec.offset, Sec.size));
|
||||
return TempSec;
|
||||
}
|
||||
|
||||
template <typename SectionType>
|
||||
MachOYAML::Section constructSection(SectionType Sec);
|
||||
|
||||
template <> MachOYAML::Section constructSection(MachO::section Sec) {
|
||||
template <>
|
||||
MachOYAML::Section MachODumper::constructSection(MachO::section Sec) {
|
||||
MachOYAML::Section TempSec = constructSectionCommon(Sec);
|
||||
TempSec.reserved3 = 0;
|
||||
return TempSec;
|
||||
}
|
||||
|
||||
template <> MachOYAML::Section constructSection(MachO::section_64 Sec) {
|
||||
template <>
|
||||
MachOYAML::Section MachODumper::constructSection(MachO::section_64 Sec) {
|
||||
MachOYAML::Section TempSec = constructSectionCommon(Sec);
|
||||
TempSec.reserved3 = Sec.reserved3;
|
||||
return TempSec;
|
||||
}
|
||||
|
||||
template <typename SectionType, typename SegmentType>
|
||||
const char *
|
||||
extractSections(const llvm::object::MachOObjectFile::LoadCommandInfo &LoadCmd,
|
||||
std::vector<MachOYAML::Section> &Sections,
|
||||
bool IsLittleEndian) {
|
||||
const char *MachODumper::extractSections(
|
||||
const llvm::object::MachOObjectFile::LoadCommandInfo &LoadCmd,
|
||||
std::vector<MachOYAML::Section> &Sections) {
|
||||
auto End = LoadCmd.Ptr + LoadCmd.C.cmdsize;
|
||||
const SectionType *Curr =
|
||||
reinterpret_cast<const SectionType *>(LoadCmd.Ptr + sizeof(SegmentType));
|
||||
for (; reinterpret_cast<const void *>(Curr) < End; Curr++) {
|
||||
if (IsLittleEndian != sys::IsLittleEndianHost) {
|
||||
if (Obj.isLittleEndian() != sys::IsLittleEndianHost) {
|
||||
SectionType Sec;
|
||||
memcpy((void *)&Sec, Curr, sizeof(SectionType));
|
||||
MachO::swapStruct(Sec);
|
||||
@ -118,8 +128,8 @@ template <>
|
||||
const char *MachODumper::processLoadCommandData<MachO::segment_command>(
|
||||
MachOYAML::LoadCommand &LC,
|
||||
const llvm::object::MachOObjectFile::LoadCommandInfo &LoadCmd) {
|
||||
return extractSections<MachO::section, MachO::segment_command>(
|
||||
LoadCmd, LC.Sections, Obj.isLittleEndian());
|
||||
return extractSections<MachO::section, MachO::segment_command>(LoadCmd,
|
||||
LC.Sections);
|
||||
}
|
||||
|
||||
template <>
|
||||
@ -127,7 +137,7 @@ const char *MachODumper::processLoadCommandData<MachO::segment_command_64>(
|
||||
MachOYAML::LoadCommand &LC,
|
||||
const llvm::object::MachOObjectFile::LoadCommandInfo &LoadCmd) {
|
||||
return extractSections<MachO::section_64, MachO::segment_command_64>(
|
||||
LoadCmd, LC.Sections, Obj.isLittleEndian());
|
||||
LoadCmd, LC.Sections);
|
||||
}
|
||||
|
||||
template <typename StructType>
|
||||
|
Loading…
Reference in New Issue
Block a user