[llvm] 3c3a6e2 - [ObjectYAML][MachO] Add error handling in MachOEmitter.
Xing GUO via llvm-commits
llvm-commits at lists.llvm.org
Wed May 27 18:51:38 PDT 2020
Author: Xing GUO
Date: 2020-05-28T09:54:46+08:00
New Revision: 3c3a6e26e7c39096b3df746faeaa743197657a8e
URL: https://github.com/llvm/llvm-project/commit/3c3a6e26e7c39096b3df746faeaa743197657a8e
DIFF: https://github.com/llvm/llvm-project/commit/3c3a6e26e7c39096b3df746faeaa743197657a8e.diff
LOG: [ObjectYAML][MachO] Add error handling in MachOEmitter.
Currently, `yaml2macho` doesn't support error handling. This patch helps improve it.
Differential Revision: https://reviews.llvm.org/D80535
Added:
Modified:
llvm/lib/ObjectYAML/MachOEmitter.cpp
llvm/test/ObjectYAML/MachO/fat_macho_i386_x86_64.yaml
llvm/test/ObjectYAML/MachO/sections.yaml
Removed:
################################################################################
diff --git a/llvm/lib/ObjectYAML/MachOEmitter.cpp b/llvm/lib/ObjectYAML/MachOEmitter.cpp
index 5a38fef50854..f8661e0c3c31 100644
--- a/llvm/lib/ObjectYAML/MachOEmitter.cpp
+++ b/llvm/lib/ObjectYAML/MachOEmitter.cpp
@@ -15,6 +15,8 @@
#include "llvm/ObjectYAML/DWARFEmitter.h"
#include "llvm/ObjectYAML/ObjectYAML.h"
#include "llvm/ObjectYAML/yaml2obj.h"
+#include "llvm/Support/Errc.h"
+#include "llvm/Support/Error.h"
#include "llvm/Support/LEB128.h"
#include "llvm/Support/YAMLTraits.h"
#include "llvm/Support/raw_ostream.h"
@@ -33,12 +35,12 @@ class MachOWriter {
memset(reinterpret_cast<void *>(&Header), 0, sizeof(MachO::mach_header_64));
}
- void writeMachO(raw_ostream &OS);
+ Error writeMachO(raw_ostream &OS);
private:
void writeHeader(raw_ostream &OS);
void writeLoadCommands(raw_ostream &OS);
- void writeSectionData(raw_ostream &OS);
+ Error writeSectionData(raw_ostream &OS);
void writeRelocations(raw_ostream &OS);
void writeLinkEditData(raw_ostream &OS);
@@ -66,14 +68,16 @@ class MachOWriter {
bool FoundLinkEditSeg = false;
};
-void MachOWriter::writeMachO(raw_ostream &OS) {
+Error MachOWriter::writeMachO(raw_ostream &OS) {
fileStart = OS.tell();
writeHeader(OS);
writeLoadCommands(OS);
- writeSectionData(OS);
+ if (Error Err = writeSectionData(OS))
+ return Err;
writeRelocations(OS);
if (!FoundLinkEditSeg)
writeLinkEditData(OS);
+ return Error::success();
}
void MachOWriter::writeHeader(raw_ostream &OS) {
@@ -261,7 +265,7 @@ void MachOWriter::writeLoadCommands(raw_ostream &OS) {
}
}
-void MachOWriter::writeSectionData(raw_ostream &OS) {
+Error MachOWriter::writeSectionData(raw_ostream &OS) {
for (auto &LC : Obj.LoadCommands) {
switch (LC.Data.load_command_data.cmd) {
case MachO::LC_SEGMENT:
@@ -277,9 +281,10 @@ void MachOWriter::writeSectionData(raw_ostream &OS) {
ZeroToOffset(OS, Sec.offset);
// Zero Fill any data between the end of the last thing we wrote and the
// start of this section.
- assert((OS.tell() - fileStart <= Sec.offset ||
- Sec.offset == (uint32_t)0) &&
- "Wrote too much data somewhere, section offsets don't line up.");
+ if (OS.tell() - fileStart > Sec.offset && Sec.offset != (uint32_t)0)
+ return createStringError(
+ errc::invalid_argument,
+ "wrote too much data somewhere, section offsets don't line up");
if (0 == strncmp(&Sec.segname[0], "__DWARF", 16)) {
if (0 == strncmp(&Sec.sectname[0], "__debug_str", 16)) {
DWARFYAML::EmitDebugStr(OS, Obj.DWARF);
@@ -323,6 +328,8 @@ void MachOWriter::writeSectionData(raw_ostream &OS) {
break;
}
}
+
+ return Error::success();
}
// The implementation of makeRelocationInfo and makeScatteredRelocationInfo is
@@ -528,7 +535,7 @@ class UniversalWriter {
UniversalWriter(yaml::YamlObjectFile &ObjectFile)
: ObjectFile(ObjectFile), fileStart(0) {}
- void writeMachO(raw_ostream &OS);
+ Error writeMachO(raw_ostream &OS);
private:
void writeFatHeader(raw_ostream &OS);
@@ -540,28 +547,33 @@ class UniversalWriter {
uint64_t fileStart;
};
-void UniversalWriter::writeMachO(raw_ostream &OS) {
+Error UniversalWriter::writeMachO(raw_ostream &OS) {
fileStart = OS.tell();
if (ObjectFile.MachO) {
MachOWriter Writer(*ObjectFile.MachO);
- Writer.writeMachO(OS);
- return;
+ return Writer.writeMachO(OS);
}
writeFatHeader(OS);
writeFatArchs(OS);
auto &FatFile = *ObjectFile.FatMachO;
- assert(FatFile.FatArchs.size() >= FatFile.Slices.size() &&
- "Cannot write Slices if not decribed in FatArches");
+ if (FatFile.FatArchs.size() < FatFile.Slices.size())
+ return createStringError(
+ errc::invalid_argument,
+ "cannot write 'Slices' if not described in 'FatArches'");
+
for (size_t i = 0; i < FatFile.Slices.size(); i++) {
ZeroToOffset(OS, FatFile.FatArchs[i].offset);
MachOWriter Writer(FatFile.Slices[i]);
- Writer.writeMachO(OS);
+ if (Error Err = Writer.writeMachO(OS))
+ return Err;
auto SliceEnd = FatFile.FatArchs[i].offset + FatFile.FatArchs[i].size;
ZeroToOffset(OS, SliceEnd);
}
+
+ return Error::success();
}
void UniversalWriter::writeFatHeader(raw_ostream &OS) {
@@ -629,9 +641,13 @@ void UniversalWriter::ZeroToOffset(raw_ostream &OS, size_t Offset) {
namespace llvm {
namespace yaml {
-bool yaml2macho(YamlObjectFile &Doc, raw_ostream &Out, ErrorHandler /*EH*/) {
+bool yaml2macho(YamlObjectFile &Doc, raw_ostream &Out, ErrorHandler EH) {
UniversalWriter Writer(Doc);
- Writer.writeMachO(Out);
+ if (Error Err = Writer.writeMachO(Out)) {
+ handleAllErrors(std::move(Err),
+ [&](const ErrorInfoBase &Err) { EH(Err.message()); });
+ return false;
+ }
return true;
}
diff --git a/llvm/test/ObjectYAML/MachO/fat_macho_i386_x86_64.yaml b/llvm/test/ObjectYAML/MachO/fat_macho_i386_x86_64.yaml
index 55a9df3636d6..b9b2f2d629e2 100644
--- a/llvm/test/ObjectYAML/MachO/fat_macho_i386_x86_64.yaml
+++ b/llvm/test/ObjectYAML/MachO/fat_macho_i386_x86_64.yaml
@@ -1,4 +1,9 @@
-# RUN: yaml2obj %s | obj2yaml | FileCheck %s
+## This file contains test cases for generating Fat Mach-O binaries.
+
+## a) Test that yaml2obj emits Fat Mach-O binary and obj2yaml converts it
+## back to YAML file.
+
+# RUN: yaml2obj --docnum=1 %s | obj2yaml | FileCheck %s
--- !fat-mach-o
FatHeader:
@@ -72,3 +77,39 @@ Slices:
#CHECK: flags: 0x00218085
#CHECK: reserved: 0x00000000
#CHECK: ...
+
+## b) Test that yaml2obj emits an error message if the number of 'FatArchs' is less than
+## the number of 'Slices'.
+
+# RUN: not yaml2obj --docnum=2 %s -o %t2.fat-macho 2>&1 | FileCheck %s --check-prefix=ERROR
+
+# ERROR: yaml2obj: error: cannot write 'Slices' if not described in 'FatArches'
+
+--- !fat-mach-o
+FatHeader:
+ magic: 0xCAFEBABE
+ nfat_arch: 2
+FatArchs:
+ ## 2 FatArchs are expected.
+ - cputype: 0x00000007
+ cpusubtype: 0x00000003
+ offset: 0x0000000000001000
+ size: 0
+ align: 0
+Slices:
+ - FileHeader:
+ magic: 0xFEEDFACE
+ cputype: 0x00000007
+ cpusubtype: 0x00000003
+ filetype: 0x00000002
+ ncmds: 0
+ sizeofcmds: 0
+ flags: 0x00000000
+ - FileHeader:
+ magic: 0xFEEDFACE
+ cputype: 0x00000007
+ cpusubtype: 0x00000003
+ filetype: 0x00000002
+ ncmds: 0
+ sizeofcmds: 0
+ flags: 0x00000000
diff --git a/llvm/test/ObjectYAML/MachO/sections.yaml b/llvm/test/ObjectYAML/MachO/sections.yaml
index 5da789dbdef7..f8c5370ecc37 100644
--- a/llvm/test/ObjectYAML/MachO/sections.yaml
+++ b/llvm/test/ObjectYAML/MachO/sections.yaml
@@ -1,4 +1,8 @@
-# RUN: yaml2obj %s | obj2yaml | FileCheck %s
+## This file contains test cases for generating sections in Mach-O object files.
+
+## a) Test that yaml2obj emits sections and obj2yaml converts them back.
+
+# RUN: yaml2obj --docnum=1 %s | obj2yaml | FileCheck %s
--- !mach-o
FileHeader:
@@ -281,3 +285,58 @@ LoadCommands:
#CHECK: segname: __DATA
#CHECK: - sectname: __la_symbol_ptr
#CHECK: segname: __DATA
+
+## b) Test that yaml2obj emits an error message if we specify an offset that
+## makes the current section and the previous one overlap.
+
+# RUN: not yaml2obj --docnum=2 %s -o %t2.macho 2>&1 | FileCheck %s --check-prefix=OVERLAP
+
+# OVERLAP: yaml2obj: error: wrote too much data somewhere, section offsets don't line up
+
+--- !mach-o
+FileHeader:
+ magic: 0xFEEDFACF
+ cputype: 0x01000007
+ cpusubtype: 0x80000003
+ filetype: 0x00000002
+ ncmds: 1
+ sizeofcmds: 1024
+ flags: 0x00000000
+ reserved: 0x00000000
+LoadCommands:
+ - cmd: LC_SEGMENT_64
+ cmdsize: 0xff
+ segname: __SEC
+ vmaddr: 0
+ vmsize: 0
+ fileoff: 0
+ filesize: 0
+ maxprot: 0
+ initprot: 0
+ nsects: 2
+ flags: 0
+ Sections:
+ - sectname: __sec1
+ segname: __SEC
+ addr: 0x0000000000000000
+ size: 2
+ offset: 0x00000000
+ align: 0
+ reloff: 0x00000000
+ nreloc: 0
+ flags: 0x00000000
+ reserved1: 0x00000000
+ reserved2: 0x00000000
+ reserved3: 0x00000000
+ - sectname: __sec2
+ segname: __SEC
+ addr: 0x0000000000000000
+ size: 2
+ offset: 0x00000001 ## Specify an offset that makes __sec1 and __sec2 overlap.
+ align: 1
+ reloff: 0x00000000
+ nreloc: 0
+ flags: 0x00000000
+ reserved1: 0x00000000
+ reserved2: 0x00000000
+ reserved3: 0x00000000
More information about the llvm-commits
mailing list