diff --git a/llvm/include/llvm/BinaryFormat/GOFF.h b/llvm/include/llvm/BinaryFormat/GOFF.h
new file mode 100644
--- /dev/null
+++ b/llvm/include/llvm/BinaryFormat/GOFF.h
@@ -0,0 +1,226 @@
+//===-- llvm/BinaryFormat/GOFF.h - GOFF definitions --------------*- C++-*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This header contains common, non-processor-specific data structures and
+// constants for the GOFF file format.
+//
+// The details of the GOFF32 bits in this file are largely based on the Tool
+// Interface Standard (TIS) Executable and Linking Format (GOFF) Specification
+// Version 1.2, May 1995. The GOFF64 specifics are based on GOFF-64 Object File
+// Format Version 1.5, Draft 2, May 1998 as well as OpenBSD header files.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_BINARYFORMAT_GOFF_H
+#define LLVM_BINARYFORMAT_GOFF_H
+
+#include "llvm/Support/DataTypes.h"
+
+namespace llvm {
+
+namespace GOFF {
+
+constexpr uint8_t RecordLength = 80;
+
+/// \brief Maximum data length before starting a new card for RLD and TXT data.
+///
+/// The maximum number of bytes that can be included in an RLD or TXT record and
+/// their continuations is a SIGNED 16 bit int despite what the spec says. The
+/// number of bytes we allow ourselves to attach to a card is thus arbitrarily
+/// limited to 16K bytes.
+constexpr uint16_t MaxDataLength = 16 * 1024;
+
+// Prefix byte on every record. This indicates GOFF format.
+enum { PTVPrefix = 0x03 };
+
+enum RecordType {
+  RT_ESD = 0,
+  RT_TXT = 1,
+  RT_RLD = 2,
+  RT_LEN = 3,
+  RT_END = 4,
+  RT_HDR = 15,
+};
+
+enum ESDSymbolType {
+  ESD_ST_SectionDefinition = 0,
+  ESD_ST_ElementDefinition = 1,
+  ESD_ST_LabelDefinition = 2,
+  ESD_ST_PartReference = 3,
+  ESD_ST_ExternalReference = 4,
+};
+
+enum ESDNameSpaceId {
+  ESD_NS_ProgramManagementBinder = 0,
+  ESD_NS_NormalName = 1,
+  ESD_NS_PseudoRegister = 2,
+  ESD_NS_Parts = 3
+};
+
+enum ESDReserveQwords {
+  ESD_RQ_0 = 0,
+  ESD_RQ_1 = 1,
+  ESD_RQ_2 = 2,
+  ESD_RQ_3 = 3
+};
+
+enum ESDERSymbolType {
+  ESD_ES_None = 0,
+  ESD_ES_Section = 1,
+  ESD_ES_Label = 2,
+  ESD_ES_Class = 3,
+  ESD_ES_Part = 4
+};
+
+enum ESDAmode {
+  ESD_AMODE_None = 0,
+  ESD_AMODE_24 = 1,
+  ESD_AMODE_31 = 2,
+  ESD_AMODE_ANY = 3,
+  ESD_AMODE_64 = 4,
+  ESD_AMODE_MIN = 16,
+};
+
+enum ESDRmode {
+  ESD_RMODE_None = 0,
+  ESD_RMODE_24 = 1,
+  ESD_RMODE_31 = 3,
+  ESD_RMODE_64 = 4,
+};
+
+enum ESDTextStyle {
+  ESD_TS_ByteOriented = 0,
+  ESD_TS_Structured = 1,
+  ESD_TS_Unstructured = 2,
+};
+
+enum ESDBindingAlgorithm {
+  ESD_BA_Concatenate = 0,
+  ESD_BA_Merge = 1,
+};
+
+enum ESDTaskingBehavior {
+  ESD_TA_Unspecified = 0,
+  ESD_TA_NonReus = 1,
+  ESD_TA_Reus = 2,
+  ESD_TA_Rent = 3,
+};
+
+enum ESDExecutable {
+  ESD_EXE_Unspecified = 0,
+  ESD_EXE_DATA = 1,
+  ESD_EXE_CODE = 2,
+};
+
+enum ESDDuplicateSymbolSeverity {
+  ESD_DSS_NoWarning = 0,
+  ESD_DSS_Warning = 1,
+  ESD_DSS_Error = 2,
+  ESD_DSS_Reserved = 3,
+};
+
+enum ESDBindingStrength {
+  ESD_BST_Strong = 0,
+  ESD_BST_Weak = 1,
+};
+
+enum ESDLoadingBehavior {
+  ESD_LB_Initial = 0,
+  ESD_LB_Deferred = 1,
+  ESD_LB_NoLoad = 2,
+  ESD_LB_Reserved = 3,
+};
+
+enum ESDBindingScope {
+  ESD_BSC_Unspecified = 0,
+  ESD_BSC_Section = 1,
+  ESD_BSC_Module = 2,
+  ESD_BSC_Library = 3,
+  ESD_BSC_ImportExport = 4,
+};
+
+enum ESDLinkageType { ESD_LT_OS = 0, ESD_LT_XPLink = 1 };
+
+enum ESDAlignment {
+  ESD_ALIGN_Byte = 0,
+  ESD_ALIGN_Halfword = 1,
+  ESD_ALIGN_Fullword = 2,
+  ESD_ALIGN_Doubleword = 3,
+  ESD_ALIGN_Quadword = 4,
+  ESD_ALIGN_32byte = 5,
+  ESD_ALIGN_64byte = 6,
+  ESD_ALIGN_128byte = 7,
+  ESD_ALIGN_256byte = 8,
+  ESD_ALIGN_512byte = 9,
+  ESD_ALIGN_1024byte = 10,
+  ESD_ALIGN_2Kpage = 11,
+  ESD_ALIGN_4Kpage = 12,
+};
+
+enum TXTRecordStyle {
+  TXT_RS_Byte = 0,
+  TXT_RS_Structured = 1,
+  TXT_RS_Unstructured = 2,
+};
+
+enum RLDReferenceType {
+  RLD_RT_RAddress = 0,
+  RLD_RT_ROffset = 1,
+  RLD_RT_RLength = 2,
+  RLD_RT_RRelativeImmediate = 6,
+  RLD_RT_RTypeConstant = 7,
+  RLD_RT_RLongDisplacement = 9,
+};
+
+enum RLDReferentType {
+  RLD_RO_Label = 0,
+  RLD_RO_Element = 1,
+  RLD_RO_Class = 2,
+  RLD_RO_Part = 3,
+};
+
+enum RLDAction {
+  RLD_ACT_Multiply = 4,
+  RLD_ACT_Div4Quotient = 6,
+  RLD_ACT_Div4Remainder = 7,
+  RLD_ACT_And = 8,
+  RLD_ACT_Or = 9,
+  RLD_ACT_Xor = 10,
+  RLD_ACT_Move = 16
+};
+
+enum RLDFetchStore { RLD_FS_Fetch = 0, RLD_FS_Store = 1 };
+
+enum ENDEntryPointRequest {
+  END_EPR_None = 0,
+  END_EPR_EsdidOffset = 1,
+  END_EPR_ExternalName = 2,
+  END_EPR_Reserved = 3,
+};
+
+// \brief Represent the different types of objects that can be referenced from
+// the associated data area (ADA) of a compilation unit.
+enum ADASlotKind {
+#define ADASLOT(SLOT, MO, V) SLOT = V,
+#include "llvm/BinaryFormat/GOFFAda.def"
+};
+
+// \brief Subsections of the primary C_CODE section in the object file.
+enum SubsectionKind {
+  SK_ReadOnly = 1,
+  SK_PPA1 = 2,
+  SK_JumpTable = 3,
+  SK_PPA2 = 4,
+};
+
+} // end namespace GOFF
+
+} // end namespace llvm
+
+#endif // LLVM_BINARYFORMAT_GOFF_H
diff --git a/llvm/include/llvm/BinaryFormat/GOFFAda.def b/llvm/include/llvm/BinaryFormat/GOFFAda.def
new file mode 100644
--- /dev/null
+++ b/llvm/include/llvm/BinaryFormat/GOFFAda.def
@@ -0,0 +1,40 @@
+//===-- GOFFAda.def ---------------------------------------------*- C++ -*-===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+//
+// This file centralizes the ADA definitions used by GOFF and XPLINK.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef ADASLOT
+#define ADASLOT(SLOT, MO, V)
+#endif
+
+/// ADASLOT(SLOT, MO, V)
+///
+/// \param SLOT - ADA slot kind in file
+/// \param MO   - Corresponding machine operand kind
+/// \param V    - Enumeration value
+
+// The address of a non-function (data) symbol.
+ADASLOT(ADA_DataSymbolAddr, MO_ADA_DATA_SYMBOL_ADDR, 1)
+// The address of a function descriptor.
+ADASLOT(ADA_IndirectFuncDesc, MO_ADA_INDIRECT_FUNC_DESC, 2)
+// A function descriptor. Contains the address of the ADA for a function and
+// the address of the function.
+ADASLOT(ADA_DirectFuncDesc, MO_ADA_DIRECT_FUNC_DESC, 3)
+// The address of the ADA for a function. Part of a function descriptor.
+ADASLOT(ADA_DirectFuncDescADA, MO_ADA_DIRECT_FUNC_DESC_ADA, 4)
+// The address of a function. Part of a function descriptor.
+ADASLOT(ADA_DirectFuncDescAddr, MO_ADA_DIRECT_FUNC_DESC_EPA, 5)
+// The address of a data symbol's handle, that is, the address of the symbol
+// referenced. This is how external data is referenced.
+ADASLOT(ADA_DataSymbolHandle, MO_ADA_DATA_SYMBOL_ADDR_VIA_HANDLE, 6)
+// Access ADA entry containing pointer to internal data symbol.
+ADASLOT(ADA_InternalDataSymbolAddr, MO_ADA_INTERNAL_DATA_SYMBOL_ADDR, 7)
+
+#undef ADASLOT
diff --git a/llvm/include/llvm/BinaryFormat/Magic.h b/llvm/include/llvm/BinaryFormat/Magic.h
--- a/llvm/include/llvm/BinaryFormat/Magic.h
+++ b/llvm/include/llvm/BinaryFormat/Magic.h
@@ -49,6 +49,7 @@
     xcoff_object_64,     ///< 64-bit XCOFF object file
     wasm_object,         ///< WebAssembly Object file
     pdb,                 ///< Windows PDB debug info file
+    goff_object,         ///< GOFF object file
     tapi_file,           ///< Text-based Dynamic Library Stub file
   };
 
diff --git a/llvm/include/llvm/Object/Binary.h b/llvm/include/llvm/Object/Binary.h
--- a/llvm/include/llvm/Object/Binary.h
+++ b/llvm/include/llvm/Object/Binary.h
@@ -67,6 +67,7 @@
     ID_MachO64L, // MachO 64-bit, little endian
     ID_MachO64B, // MachO 64-bit, big endian
 
+    ID_GOFF,
     ID_Wasm,
 
     ID_EndObjects
@@ -139,6 +140,8 @@
     return TypeID == ID_IR;
   }
 
+  bool isGOFF() const { return TypeID == ID_GOFF; }
+
   bool isMinidump() const { return TypeID == ID_Minidump; }
 
   bool isTapiFile() const { return TypeID == ID_TapiFile; }
@@ -157,6 +160,8 @@
       return Triple::MachO;
     if (isELF())
       return Triple::ELF;
+    if (isGOFF())
+      return Triple::GOFF;
     return Triple::UnknownObjectFormat;
   }
 
diff --git a/llvm/include/llvm/Object/GOFF.h b/llvm/include/llvm/Object/GOFF.h
new file mode 100644
--- /dev/null
+++ b/llvm/include/llvm/Object/GOFF.h
@@ -0,0 +1,537 @@
+//===- GOFF.h - GOFF object file implementation -----------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares the GOFFObjectFile class.
+// Record classes and derivatives are also declared and implemented.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_OBJECT_GOFF_H
+#define LLVM_OBJECT_GOFF_H
+
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/BinaryFormat/GOFF.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/Endian.h"
+#include "llvm/Support/raw_ostream.h"
+
+namespace llvm {
+
+struct GOFFRelocationEntry {
+  const uint32_t REsdId;
+  const uint32_t PEsdId;
+  const uint64_t POffset;
+
+  const GOFF::RLDReferenceType ReferenceType;
+  const GOFF::RLDReferentType ReferentType;
+  const GOFF::RLDAction Action;
+  const bool NoFetchTarget;
+  const uint32_t TargetLength;
+
+  GOFFRelocationEntry(uint32_t REsdId, uint32_t PEsdId, uint64_t POffset,
+                      GOFF::RLDReferenceType ReferenceType,
+                      GOFF::RLDReferentType ReferentType,
+                      GOFF::RLDAction Action, bool NoFetchTarget,
+                      uint32_t TargetLength)
+      : REsdId(REsdId), PEsdId(PEsdId), POffset(POffset),
+        ReferenceType(ReferenceType), ReferentType(ReferentType),
+        Action(Action), NoFetchTarget(NoFetchTarget),
+        TargetLength(TargetLength) {}
+};
+
+namespace object {
+
+/// \brief Represents a GOFF physical record.
+///
+/// Specifies protected member functions to manipulate the record. These should
+/// be called from deriving classes to change values as that record specifies.
+class Record {
+  SmallVector<char, GOFF::RecordLength> Bytes;
+
+public:
+  Record() : Bytes(GOFF::RecordLength, (char)0x00) {
+    set<uint8_t>(0, GOFF::PTVPrefix);
+  };
+
+  // Set PTV fields common to all records.
+  void setRecordType(GOFF::RecordType RecordType) {
+    setBits(1, 0, 4, RecordType);
+  }
+
+  void setContinuation(bool Continuation) {
+    uint8_t Value = Continuation ? 1 : 0;
+    setBits(1, 6, 1, Value);
+  }
+
+  void setContinued(bool Continued) {
+    uint8_t Value = Continued ? 1 : 0;
+    setBits(1, 7, 1, Value);
+  }
+
+  const SmallVectorImpl<char> &getBytes() const { return Bytes; }
+
+protected:
+  /// \brief Set bit field of specified byte.
+  ///
+  /// Used to pack bit fields into one byte. Fields are packed LEFT TO RIGHT.
+  /// Bit index zero is the MOST SIGNIFICANT BIT of the byte.
+  ///
+  /// \param ByteIndex index of byte the field is in.
+  /// \param BitIndex index of first bit of field.
+  /// \param Length length of bit field.
+  /// \param Value new value of bit field.
+  void setBits(uint8_t ByteIndex, uint8_t BitIndex, uint8_t Length,
+               uint8_t Value) {
+    assert(ByteIndex < GOFF::RecordLength && "Byte index out of bounds!");
+    assert(BitIndex < 8 && "Bit index out of bounds!");
+    assert(Length + BitIndex <= 8 && "Bit length too long!");
+
+    uint8_t Mask = ((1 << Length) - 1) << (8 - BitIndex - Length);
+    Value = Value << (8 - BitIndex - Length);
+    assert((Value & Mask) == Value && "Bits set outside of range!");
+
+    uint8_t PrevValue;
+    get<uint8_t>(reinterpret_cast<const uint8_t *>(Bytes.data()), ByteIndex,
+                 PrevValue);
+    set<uint8_t>(ByteIndex, (PrevValue & ~Mask) | Value);
+  }
+
+  // Set byte of record
+  template <class T> void set(uint8_t ByteIndex, T Value) {
+    assert(ByteIndex + sizeof(T) - 1 < GOFF::RecordLength &&
+           "Byte index out of bounds!");
+    support::endian::write<T, support::big, support::unaligned>(
+        &Bytes[ByteIndex], Value);
+  }
+
+  static void getBits(const uint8_t *Bytes, uint8_t ByteIndex, uint8_t BitIndex,
+                      uint8_t Length, uint8_t &Value) {
+    assert(ByteIndex < GOFF::RecordLength && "Byte index out of bounds!");
+    assert(BitIndex < 8 && "Bit index out of bounds!");
+    assert(Length + BitIndex <= 8 && "Bit length too long!");
+
+    get<uint8_t>(Bytes, ByteIndex, Value);
+    uint8_t Mask = ((1 << Length) - 1) << (8 - BitIndex - Length);
+    Value = (Value & Mask) >> (8 - BitIndex - Length);
+  }
+
+  template <class T>
+  static void get(const uint8_t *Bytes, uint8_t ByteIndex, T &Value) {
+    assert(ByteIndex + sizeof(T) - 1 < GOFF::RecordLength &&
+           "Byte index out of bounds!");
+    Value = support::endian::read<T, support::big, support::unaligned>(
+        &Bytes[ByteIndex]);
+  }
+};
+
+class HDRRecord : public Record {
+public:
+  HDRRecord() : Record() {
+    setRecordType(GOFF::RT_HDR);
+    setArchitectureLevel(1);
+  }
+
+  void setArchitectureLevel(uint32_t Level) { set<uint32_t>(48, Level); }
+};
+
+class TXTRecord : public Record {
+public:
+  /// \brief Maximum length of data; any more must go in continuation.
+  static const uint8_t TXTMaxDataLength = 56;
+
+public:
+  TXTRecord() : Record() { setRecordType(GOFF::RT_TXT); }
+
+  void setRecordStyle(GOFF::TXTRecordStyle Style) { setBits(3, 4, 4, Style); }
+
+  void setElementEsdId(uint32_t EsdId) { set<uint32_t>(4, EsdId); }
+
+  void setOffset(uint32_t Offset) { set<uint32_t>(12, Offset); }
+
+  void setDataLength(uint16_t Length) { set<uint16_t>(22, Length); }
+
+  void setData(const SmallVectorImpl<char>::const_iterator &Data,
+               uint8_t Length) {
+    assert(Length <= TXTMaxDataLength && "Data too long for TXT Record");
+
+    for (int I = 0; I < Length; ++I)
+      set<uint8_t>(24 + I, Data[I]);
+  }
+
+  // Get routines.
+  static void getElementEsdId(const uint8_t *Record, uint32_t &EsdId) {
+    get<uint32_t>(Record, 4, EsdId);
+  }
+
+  static void getOffset(const uint8_t *Record, uint32_t &Offset) {
+    get<uint32_t>(Record, 12, Offset);
+  }
+
+  static void getDataLength(const uint8_t *Record, uint16_t &Length) {
+    get<uint16_t>(Record, 22, Length);
+  }
+};
+
+class ESDRecord : public Record {
+public:
+  /// \brief Number of bytes for name; any more must go in continuation.
+  /// This is the number of bytes that can fit into the data field of an ESD
+  /// record.
+  static const uint8_t ESDMaxNameLength = 8;
+
+  /// \brief Maximum name length for ESD records and continuations.
+  /// This is the number of bytes that can fit into the data field of an ESD
+  /// record AND following continuations. This is limited fundamentally by the
+  /// 16 bit SIGNED length field.
+  static const uint16_t MaxNameLength = 32 * 1024;
+
+public:
+  ESDRecord() : Record() { setRecordType(GOFF::RT_ESD); }
+
+  void setSymbolType(GOFF::ESDSymbolType SymbolType) {
+    set<uint8_t>(3, SymbolType);
+  }
+
+  void setEsdId(uint32_t EsdId) { set<uint32_t>(4, EsdId); }
+
+  void setParentEsdId(uint32_t EsdId) { set<uint32_t>(8, EsdId); }
+
+  void setOffset(uint32_t Offset) { set<uint32_t>(16, Offset); }
+
+  void setLength(uint32_t Length) { set<uint32_t>(24, Length); }
+
+  void setNameSpaceId(GOFF::ESDNameSpaceId Id) { set<uint8_t>(40, Id); }
+
+  void setFillBytePresent(bool Present) { setBits(41, 0, 1, Present); }
+
+  void setNameMangled(bool Mangled) { setBits(41, 1, 1, Mangled); }
+
+  void setRenamable(bool Renamable) { setBits(41, 2, 1, Renamable); }
+
+  void setRemovable(bool Removable) { setBits(41, 3, 1, Removable); }
+
+  void setReserveQwords(GOFF::ESDReserveQwords Reserve) {
+    setBits(41, 5, 3, Reserve);
+  }
+
+  // This intentionally uses the same field as above.
+  void setERSymbolType(GOFF::ESDERSymbolType Type) { setBits(41, 5, 3, Type); }
+
+  void setFillByteValue(uint8_t Fill) { set<uint8_t>(42, Fill); }
+
+  void setAdaEsdId(uint32_t EsdId) { set<uint32_t>(44, EsdId); }
+
+  void setSortPriority(uint32_t Priority) { set<uint32_t>(48, Priority); }
+
+  void setAmode(GOFF::ESDAmode Amode) { set<uint8_t>(60, Amode); }
+
+  void setRmode(GOFF::ESDRmode Rmode) { set<uint8_t>(61, Rmode); }
+
+  void setTextStyle(GOFF::ESDTextStyle Style) { setBits(62, 0, 4, Style); }
+
+  void setBindingAlgorithm(GOFF::ESDBindingAlgorithm Algorithm) {
+    setBits(62, 4, 4, Algorithm);
+  }
+
+  void setTaskingBehavior(GOFF::ESDTaskingBehavior TaskingBehavior) {
+    setBits(63, 0, 3, TaskingBehavior);
+  }
+
+  void setReadOnly(bool ReadOnly) {
+    uint8_t Value = ReadOnly ? 1 : 0;
+    setBits(63, 4, 1, Value);
+  }
+
+  void setExecutable(GOFF::ESDExecutable Executable) {
+    setBits(63, 5, 3, Executable);
+  }
+
+  void setDuplicateSeverity(GOFF::ESDDuplicateSymbolSeverity DSS) {
+    setBits(64, 2, 2, DSS);
+  }
+
+  void setBindingStrength(GOFF::ESDBindingStrength Strength) {
+    setBits(64, 4, 4, Strength);
+  }
+
+  void setLoadingBehavior(GOFF::ESDLoadingBehavior Behavior) {
+    setBits(65, 0, 2, Behavior);
+  }
+
+  void setIndirectReference(bool Indirect) {
+    uint8_t Value = Indirect ? 1 : 0;
+    setBits(65, 3, 1, Value);
+  }
+
+  void setBindingScope(GOFF::ESDBindingScope Scope) {
+    setBits(65, 4, 4, Scope);
+  }
+
+  void setLinkageType(GOFF::ESDLinkageType Type) { setBits(66, 2, 1, Type); }
+
+  void setAlignment(GOFF::ESDAlignment Alignment) {
+    setBits(66, 3, 5, Alignment);
+  }
+
+  void setNameLength(uint16_t Length) { set<uint16_t>(70, Length); }
+
+  void setName(const StringRef::const_iterator &Data, uint8_t Length) {
+    assert(Length <= ESDMaxNameLength && "Data too long for ESD Record");
+
+    for (int I = 0; I < Length; ++I)
+      set<uint8_t>(72 + I, Data[I]);
+  }
+
+  // ESD Get routines.
+  static void getSymbolType(const uint8_t *Record,
+                            GOFF::ESDSymbolType &SymbolType) {
+    uint8_t Value;
+    get<uint8_t>(Record, 3, Value);
+    SymbolType = (GOFF::ESDSymbolType)Value;
+  }
+
+  static void getEsdId(const uint8_t *Record, uint32_t &EsdId) {
+    get<uint32_t>(Record, 4, EsdId);
+  }
+
+  static void getParentEsdId(const uint8_t *Record, uint32_t &EsdId) {
+    get<uint32_t>(Record, 8, EsdId);
+  }
+
+  static void getOffset(const uint8_t *Record, uint32_t &Offset) {
+    get<uint32_t>(Record, 16, Offset);
+  }
+
+  static void getLength(const uint8_t *Record, uint32_t &Length) {
+    get<uint32_t>(Record, 24, Length);
+  }
+
+  static void getNameSpaceId(const uint8_t *Record, GOFF::ESDNameSpaceId &Id) {
+    uint8_t Value;
+    get<uint8_t>(Record, 40, Value);
+    Id = (GOFF::ESDNameSpaceId)Value;
+  }
+
+  static void getFillBytePresent(const uint8_t *Record, bool &Present) {
+    uint8_t Value;
+    getBits(Record, 41, 0, 1, Value);
+    Present = (bool)Value;
+  }
+
+  static void getNameMangled(const uint8_t *Record, bool &Mangled) {
+    uint8_t Value;
+    getBits(Record, 41, 1, 1, Value);
+    Mangled = (bool)Value;
+  }
+
+  static void getRenamable(const uint8_t *Record, bool &Renamable) {
+    uint8_t Value;
+    getBits(Record, 41, 2, 1, Value);
+    Renamable = (bool)Value;
+  }
+
+  static void getRemovable(const uint8_t *Record, bool &Removable) {
+    uint8_t Value;
+    getBits(Record, 41, 3, 1, Value);
+    Removable = (bool)Value;
+  }
+
+  // This intentionally uses the same field as above.
+  static void getERSymbolType(const uint8_t *Record,
+                              GOFF::ESDERSymbolType &Type) {
+    uint8_t Value;
+    getBits(Record, 41, 5, 3, Value);
+    Type = (GOFF::ESDERSymbolType)Value;
+  }
+
+  static void getFillByteValue(const uint8_t *Record, uint8_t &Fill) {
+    get<uint8_t>(Record, 42, Fill);
+  }
+
+  static void getAdaEsdId(const uint8_t *Record, uint32_t &EsdId) {
+    get<uint32_t>(Record, 44, EsdId);
+  }
+
+  static void getSortPriority(const uint8_t *Record, uint32_t &Priority) {
+    get<uint32_t>(Record, 48, Priority);
+  }
+
+  static void getAmode(const uint8_t *Record, GOFF::ESDAmode &Amode) {
+    uint8_t Value;
+    get<uint8_t>(Record, 60, Value);
+    Amode = (GOFF::ESDAmode)Value;
+  }
+
+  static void getRmode(const uint8_t *Record, GOFF::ESDRmode &Rmode) {
+    uint8_t Value;
+    get<uint8_t>(Record, 61, Value);
+    Rmode = (GOFF::ESDRmode)Value;
+  }
+
+  static void getTextStyle(const uint8_t *Record, GOFF::ESDTextStyle &Style) {
+    uint8_t Value;
+    getBits(Record, 62, 0, 4, Value);
+    Style = (GOFF::ESDTextStyle)Value;
+  }
+
+  static void getBindingAlgorithm(const uint8_t *Record,
+                                  GOFF::ESDBindingAlgorithm &Algorithm) {
+    uint8_t Value;
+    getBits(Record, 62, 4, 4, Value);
+    Algorithm = (GOFF::ESDBindingAlgorithm)Value;
+  }
+
+  static void getTaskingBehavior(const uint8_t *Record,
+                                 GOFF::ESDTaskingBehavior &TaskingBehavior) {
+    uint8_t Value;
+    getBits(Record, 63, 0, 3, Value);
+    TaskingBehavior = (GOFF::ESDTaskingBehavior)Value;
+  }
+
+  static void getReadOnly(const uint8_t *Record, bool &ReadOnly) {
+    uint8_t Value;
+    getBits(Record, 63, 4, 1, Value);
+    ReadOnly = (bool)Value;
+  }
+
+  static void getExecutable(const uint8_t *Record,
+                            GOFF::ESDExecutable &Executable) {
+    uint8_t Value;
+    getBits(Record, 63, 5, 3, Value);
+    Executable = (GOFF::ESDExecutable)Value;
+  }
+
+  static void getDuplicateSeverity(const uint8_t *Record,
+                                   GOFF::ESDDuplicateSymbolSeverity &DSS) {
+    uint8_t Value;
+    getBits(Record, 64, 2, 2, Value);
+    DSS = (GOFF::ESDDuplicateSymbolSeverity)Value;
+  }
+
+  static void getBindingStrength(const uint8_t *Record,
+                                 GOFF::ESDBindingStrength &Strength) {
+    uint8_t Value;
+    getBits(Record, 64, 4, 4, Value);
+    Strength = (GOFF::ESDBindingStrength)Value;
+  }
+
+  static void getLoadingBehavior(const uint8_t *Record,
+                                 GOFF::ESDLoadingBehavior &Behavior) {
+    uint8_t Value;
+    getBits(Record, 65, 0, 2, Value);
+    Behavior = (GOFF::ESDLoadingBehavior)Value;
+  }
+
+  static void getIndirectReference(const uint8_t *Record, bool &Indirect) {
+    uint8_t Value;
+    getBits(Record, 65, 3, 1, Value);
+    Indirect = (bool)Value;
+  }
+
+  static void getBindingScope(const uint8_t *Record,
+                              GOFF::ESDBindingScope &Scope) {
+    uint8_t Value;
+    getBits(Record, 65, 4, 4, Value);
+    Scope = (GOFF::ESDBindingScope)Value;
+  }
+
+  static void getLinkageType(const uint8_t *Record,
+                             GOFF::ESDLinkageType &Type) {
+    uint8_t Value;
+    getBits(Record, 66, 2, 1, Value);
+    Type = (GOFF::ESDLinkageType)Value;
+  }
+
+  static void getAlignment(const uint8_t *Record,
+                           GOFF::ESDAlignment &Alignment) {
+    uint8_t Value;
+    getBits(Record, 66, 3, 5, Value);
+    Alignment = (GOFF::ESDAlignment)Value;
+  }
+};
+
+class RLDRecord : public Record {
+public:
+  /// \brief Maximum length of data; any more must go in another continuation.
+  static const uint8_t RLDMaxDataLength = 74;
+
+  /// \brief Lenght in bytes of one full relocation entry. We don't pack EsdIds.
+  static const uint8_t DataEntryLength = 20;
+
+public:
+  RLDRecord() : Record() { setRecordType(GOFF::RT_RLD); }
+
+  void setLength(uint16_t Length) { set<uint16_t>(4, Length); }
+
+  void setData(const GOFFRelocationEntry &Ent, uint8_t Index) {
+    assert(Index < 2 && "Can only store two entries per RLD Record");
+
+    uint8_t Offset = 6 + DataEntryLength * Index;
+
+    setBits(Offset + 1, 0, 4, Ent.ReferenceType);
+    setBits(Offset + 1, 4, 4, Ent.ReferentType);
+    setBits(Offset + 2, 0, 7, Ent.Action);
+    if (Ent.NoFetchTarget)
+      setBits(Offset + 2, 7, 1, 1);
+    else
+      setBits(Offset + 2, 7, 1, 0);
+    set<uint8_t>(Offset + 4, Ent.TargetLength);
+    set<uint32_t>(Offset + 8, Ent.REsdId);
+    set<uint32_t>(Offset + 12, Ent.PEsdId);
+    set<uint32_t>(Offset + 16, Ent.POffset);
+  }
+
+  // RLD Get routines.
+  static void getLength(const uint8_t *Record, uint16_t &Length) {
+    get<uint16_t>(Record, 4, Length);
+  }
+};
+
+class ContinuationRecord : public Record {
+public:
+  /// \brief Maximum length of data; any more must go in another continuation.
+  static const uint8_t ContinuationMaxDataLength = 77;
+
+public:
+  ContinuationRecord(GOFF::RecordType Type) : Record() {
+    setRecordType(Type);
+    setContinuation(true);
+  }
+
+  void setData(const char *Data, uint8_t Length) {
+    assert(Length <= ContinuationMaxDataLength &&
+           "Data too long for Continuation Record");
+
+    for (int I = 0; I < Length; ++I)
+      set<uint8_t>(3 + I, Data[I]);
+  }
+};
+
+class ENDRecord : public Record {
+public:
+  ENDRecord() : Record() {
+    setRecordType(GOFF::RT_END);
+    setEntryPointRequestType(GOFF::END_EPR_None); // TODO Always None for now.
+  }
+
+  void setEntryPointRequestType(GOFF::ENDEntryPointRequest Eprt) {
+    setBits(3, 6, 2, Eprt);
+  }
+
+  void setEntryAmode(GOFF::ESDAmode Amode) { set<uint8_t>(4, Amode); }
+
+  void setEntryEsdId(uint32_t EsdId) { set<uint32_t>(12, EsdId); }
+
+  void setRecordCount(uint32_t RecordCount) { set<uint32_t>(8, RecordCount); }
+};
+
+} // end namespace object
+} // end namespace llvm
+
+#endif
diff --git a/llvm/include/llvm/Object/GOFFObjectFile.h b/llvm/include/llvm/Object/GOFFObjectFile.h
new file mode 100644
--- /dev/null
+++ b/llvm/include/llvm/Object/GOFFObjectFile.h
@@ -0,0 +1,170 @@
+//===- GOFF.h - GOFF object file implementation -----------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares the GOFFObjectFile class.
+// Record classes and derivatives are also declared and implemented.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_OBJECT_GOFFOBJECTFILE_H
+#define LLVM_OBJECT_GOFFOBJECTFILE_H
+
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/IndexedMap.h"
+#include "llvm/ADT/Triple.h"
+#include "llvm/BinaryFormat/GOFF.h"
+#include "llvm/MC/SubtargetFeature.h"
+#include "llvm/Object/ObjectFile.h"
+#include "llvm/Support/CharSet.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/Endian.h"
+#include "llvm/Support/raw_ostream.h"
+
+namespace llvm {
+
+namespace object {
+
+class GOFFObjectFile : public ObjectFile {
+
+  IndexedMap<uintptr_t> EsdPtrs; // Indexed by EsdId.
+  SmallVector<uintptr_t, 256> TextPtrs;
+  SmallVector<uintptr_t, 256> RldPtrs;
+
+  mutable DenseMap<uint32_t, std::string> EsdNames;
+
+  typedef DataRefImpl SectionEntryImpl;
+  // (EDID, 0)               code, r/o data section
+  // (EDID,PRID)             r/w data section
+  SmallVector<SectionEntryImpl, 256> SectionList;
+  mutable DenseMap<uint32_t, std::string> SectionData;
+
+  std::string RelocationData;
+
+  CharSetConverter Converter;
+
+  // GOFF specific.
+public:
+  std::error_code getSymbolName(SymbolRef Symbol, StringRef &Res) const;
+
+  static GOFF::RLDAction getRLDAction(uint64_t RelocationType); // +,-,...
+  static GOFF::RLDFetchStore getRLDFetchStore(uint64_t RelocationType);
+  static uint16_t getRLDBitLength(uint64_t RelocationType);
+  static uint8_t getRLDBitOffset(uint64_t RelocationType);
+  static bool
+  getRLDSymbolIsIndirect(uint64_t RelocationType); // Function descriptor ref.
+  static bool getRLDIsWeak(uint64_t RelocationType); // Weak ref.
+  static bool
+  getRLDIsCodeAddressReference(uint64_t RelocationType); // Function code ref.
+
+  GOFFObjectFile(MemoryBufferRef Object, Error &Err);
+  static inline bool classof(const Binary *V) { return V->isGOFF(); }
+  section_iterator section_begin() const override;
+  section_iterator section_end() const override;
+
+  uint8_t getBytesInAddress() const override { return 8; }
+
+  StringRef getFileFormatName() const override { return "GOFF-SystemZ"; }
+
+  Triple::ArchType getArch() const override { return Triple::systemz; }
+
+  SubtargetFeatures getFeatures() const override { return SubtargetFeatures(); }
+
+  bool isRelocatableObject() const override { return true; }
+
+  void moveSymbolNext(DataRefImpl &Symb) const override;
+  basic_symbol_iterator symbol_begin() const override;
+  basic_symbol_iterator symbol_end() const override;
+
+private:
+  // SymbolRef.
+  Expected<StringRef> getSymbolName(DataRefImpl Symb) const override;
+  Expected<uint64_t> getSymbolAddress(DataRefImpl Symb) const override;
+  uint64_t getSymbolValueImpl(DataRefImpl Symb) const override;
+  uint64_t getCommonSymbolSizeImpl(DataRefImpl Symb) const override;
+  Expected<uint32_t> getSymbolFlags(DataRefImpl Symb) const override;
+  Expected<SymbolRef::Type> getSymbolType(DataRefImpl Symb) const override;
+  Expected<section_iterator> getSymbolSection(DataRefImpl Symb) const override;
+
+  const uint8_t *getSymbolEsdRecord(DataRefImpl Symb) const;
+  bool isSymbolUnresolved(DataRefImpl Symb) const;
+  bool isSymbolIndirect(DataRefImpl Symb) const;
+
+  // SectionRef.
+  void moveSectionNext(DataRefImpl &Sec) const override {};
+  virtual Expected<StringRef> getSectionName(DataRefImpl Sec) const override {
+    return StringRef();
+  }
+  uint64_t getSectionAddress(DataRefImpl Sec) const override { return 0; }
+  uint64_t getSectionSize(DataRefImpl Sec) const override { return 0; }
+  virtual Expected<ArrayRef<uint8_t>>
+  getSectionContents(DataRefImpl Sec) const override {
+    return ArrayRef<uint8_t>();
+  }
+  uint64_t getSectionIndex(DataRefImpl Sec) const override { return 0; }
+  uint64_t getSectionAlignment(DataRefImpl Sec) const override { return 0; }
+  bool isSectionCompressed(DataRefImpl Sec) const override { return false; }
+  bool isSectionText(DataRefImpl Sec) const override { return false; }
+  bool isSectionData(DataRefImpl Sec) const override { return false; }
+  bool isSectionBSS(DataRefImpl Sec) const override { return false; }
+  bool isSectionVirtual(DataRefImpl Sec) const override { return false; }
+  relocation_iterator section_rel_begin(DataRefImpl Sec) const override {
+    return relocation_iterator(RelocationRef(Sec, this));
+  }
+  relocation_iterator section_rel_end(DataRefImpl Sec) const override {
+    return relocation_iterator(RelocationRef(Sec, this));
+  }
+
+  const uint8_t *getSectionEdEsdRecord(DataRefImpl &Sec) const;
+  const uint8_t *getSectionPrEsdRecord(DataRefImpl &Sec) const;
+  const uint8_t *getSectionEdEsdRecord(uint32_t SectionIndex) const;
+  const uint8_t *getSectionPrEsdRecord(uint32_t SectionIndex) const;
+
+  struct RelocationIteratorState {
+    // Common output.
+    DataRefImpl Sec;         // Section containing relocation.
+    uint64_t PosOffset;      // Offset of relocation in Sec.
+    DataRefImpl RefSymb;     // Symbol referred to.
+    uint64_t RelocationType; // Type of relocation.
+
+    // Fields used when processing relocations from object file.
+    uint32_t RelocationDataOffset;
+    uint16_t CurrentRldSize;
+
+    uint32_t SectionDefId;
+
+    // Optional RLD fields whose value is inherited from a previous RLD item.
+    uint32_t OReferenceId;
+    uint32_t OPositionId;
+    uint64_t OOffset;
+
+    // Fields when processing relocations for manufactured function descriptor
+    // section.
+    uint32_t FunctionDescriptorIndex;
+    bool DoingFuncSymb;
+  };
+
+  // RelocationRef.
+  void moveRelocationNext(DataRefImpl &Rel) const override {};
+  uint64_t getRelocationOffset(DataRefImpl Rel) const override { return 0; }
+  symbol_iterator getRelocationSymbol(DataRefImpl Rel) const override {
+    RelocationIteratorState *RIS = (RelocationIteratorState *)Rel.p;
+    return basic_symbol_iterator(SymbolRef(RIS->RefSymb, this));
+  }
+  uint64_t getRelocationType(DataRefImpl Rel) const override { return 0; }
+  void getRelocationTypeName(DataRefImpl Rel,
+                             SmallVectorImpl<char> &Result) const override {};
+
+  void getRelocationData();
+};
+
+} // namespace object
+
+} // namespace llvm
+
+#endif
diff --git a/llvm/include/llvm/Object/ObjectFile.h b/llvm/include/llvm/Object/ObjectFile.h
--- a/llvm/include/llvm/Object/ObjectFile.h
+++ b/llvm/include/llvm/Object/ObjectFile.h
@@ -374,6 +374,9 @@
                         uint32_t UniversalCputype = 0,
                         uint32_t UniversalIndex = 0);
 
+  static Expected<std::unique_ptr<ObjectFile>>
+  createGOFFObjectFile(MemoryBufferRef Object);
+
   static Expected<std::unique_ptr<WasmObjectFile>>
   createWasmObjectFile(MemoryBufferRef Object);
 };
diff --git a/llvm/lib/BinaryFormat/Magic.cpp b/llvm/lib/BinaryFormat/Magic.cpp
--- a/llvm/lib/BinaryFormat/Magic.cpp
+++ b/llvm/lib/BinaryFormat/Magic.cpp
@@ -83,7 +83,10 @@
     if (startswith(Magic, "!<arch>\n") || startswith(Magic, "!<thin>\n"))
       return file_magic::archive;
     break;
-
+  case 0x03:
+    if (startswith(Magic, "\x03\xF0\x00"))
+      return file_magic::goff_object;
+    break;
   case '\177':
     if (startswith(Magic, "\177ELF") && Magic.size() >= 18) {
       bool Data2MSB = Magic[5] == 2;
diff --git a/llvm/lib/Object/Binary.cpp b/llvm/lib/Object/Binary.cpp
--- a/llvm/lib/Object/Binary.cpp
+++ b/llvm/lib/Object/Binary.cpp
@@ -68,6 +68,7 @@
   case file_magic::macho_kext_bundle:
   case file_magic::coff_object:
   case file_magic::coff_import_library:
+  case file_magic::goff_object:
   case file_magic::pecoff_executable:
   case file_magic::bitcode:
   case file_magic::xcoff_object_32:
diff --git a/llvm/lib/Object/CMakeLists.txt b/llvm/lib/Object/CMakeLists.txt
--- a/llvm/lib/Object/CMakeLists.txt
+++ b/llvm/lib/Object/CMakeLists.txt
@@ -9,6 +9,7 @@
   ELF.cpp
   ELFObjectFile.cpp
   Error.cpp
+  GOFFObjectFile.cpp
   IRObjectFile.cpp
   IRSymtab.cpp
   MachOObjectFile.cpp
diff --git a/llvm/lib/Object/GOFFObjectFile.cpp b/llvm/lib/Object/GOFFObjectFile.cpp
new file mode 100644
--- /dev/null
+++ b/llvm/lib/Object/GOFFObjectFile.cpp
@@ -0,0 +1,480 @@
+//===- GOFFObjectFile.cpp - GOFF object file implementation -----*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Implementation of the GOFFObjectFile class.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Object/GOFFObjectFile.h"
+#include "llvm/BinaryFormat/GOFF.h"
+#include "llvm/Object/GOFF.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/raw_ostream.h"
+
+#ifndef DEBUG_TYPE
+#define DEBUG_TYPE "goff"
+#endif
+
+using namespace llvm;
+using namespace object;
+
+#define RLD_INDIRECT_FLAG 0x400000000
+#define RLD_CODE_ADDR_FLAG 0x200000000
+#define RLD_WEAK_FLAG 0x100000000
+
+Expected<std::unique_ptr<ObjectFile>>
+ObjectFile::createGOFFObjectFile(MemoryBufferRef Object) {
+  Error Err = Error::success();
+  std::unique_ptr<GOFFObjectFile> Ret(new GOFFObjectFile(Object, Err));
+  if (Err)
+    return std::move(Err);
+  return std::move(Ret);
+}
+
+GOFFObjectFile::GOFFObjectFile(MemoryBufferRef Object, Error &Err)
+    : ObjectFile(Binary::ID_GOFF, Object),
+      Converter(cantFail(errorOrToExpected(CharSetConverter::create(
+          CharSetConverter::CP_IBM1047, CharSetConverter::CP_UTF8)))) {
+  ErrorAsOutParameter ErrAsOutParam(&Err);
+  // Object file isn't the right size, bail out early.
+  if ((Object.getBufferSize() % GOFF::RecordLength) != 0) {
+    Err = errorCodeToError(object_error::unexpected_eof);
+    return;
+  }
+
+  SectionEntryImpl DummySection;
+  SectionList.emplace_back(DummySection); // Dummy entry at index 0.
+
+  const uint8_t *End = reinterpret_cast<const uint8_t *>(Data.getBufferEnd());
+  for (const uint8_t *I = base(); I < End; I += GOFF::RecordLength) {
+    uint8_t RecordType = (I[1] & 0xF0) >> 4;
+    bool IsContinuation = I[1] & 0x02;
+
+    // Don't parse continuations records, they've already been handled by
+    // a previous record parse call
+    if (IsContinuation)
+      continue;
+
+    for (size_t J = 0; J < GOFF::RecordLength; ++J) {
+      const uint8_t *P = I + J;
+      if (J % 8 == 0)
+        LLVM_DEBUG(dbgs() << "  ");
+
+      LLVM_DEBUG(dbgs() << format("%02hhX", *P));
+    }
+    switch (RecordType) {
+    case GOFF::RT_ESD: {
+      // Save ESD record
+      uint32_t EsdId;
+      ESDRecord::getEsdId(I, EsdId);
+      EsdPtrs.grow(EsdId);
+      EsdPtrs[EsdId] = reinterpret_cast<uintptr_t>(I);
+
+      // Determine and save the "sections" in GOFF.
+      // A section is saved as a tuple of the form
+      // case (1): (ED,child PR)
+      //    - where the PR must be have non-zero length.
+      // case (2a) (ED,0)
+      //   - where the ED is of non-zero length
+      // case (2b) (ED,0)
+      //   - where the ED is zero length but
+      //     but contains a label (LD)
+      GOFF::ESDSymbolType SymbolType;
+      ESDRecord::getSymbolType(I, SymbolType);
+      SectionEntryImpl Section;
+      uint32_t Length;
+      ESDRecord::getLength(I, Length);
+      if (SymbolType == GOFF::ESD_ST_ElementDefinition) {
+        // case (2a)
+        if (Length != 0) {
+          Section.d.a = EsdId;
+          SectionList.emplace_back(Section);
+        }
+      } else if (SymbolType == GOFF::ESD_ST_PartReference) {
+        // case (1)
+        if (Length != 0) {
+          uint32_t SymEdId;
+          ESDRecord::getParentEsdId(I, SymEdId);
+          Section.d.a = SymEdId;
+          Section.d.b = EsdId;
+          SectionList.emplace_back(Section);
+        }
+      } else if (SymbolType == GOFF::ESD_ST_LabelDefinition) {
+        // case (2b)
+        uint32_t SymEdId;
+        ESDRecord::getParentEsdId(I, SymEdId);
+        const uint8_t *SymEdRecord =
+            reinterpret_cast<const uint8_t *>(EsdPtrs[SymEdId]);
+        uint32_t EdLength;
+        ESDRecord::getLength(SymEdRecord, EdLength);
+        if (!EdLength) { // [ EDID, PRID ]
+          // LD child of a zero length parent ED
+          // Add the section ED which was previously ignored
+          Section.d.a = SymEdId;
+          SectionList.emplace_back(Section);
+        }
+      }
+      LLVM_DEBUG(dbgs() << "  --  ESD " << EsdId << "\n");
+      break;
+    }
+    case GOFF::RT_TXT:
+      // Save TXT records
+      TextPtrs.emplace_back(reinterpret_cast<uintptr_t>(I));
+      LLVM_DEBUG(dbgs() << "  --  TXT\n");
+      break;
+    case GOFF::RT_RLD:
+      // Save RLD records
+      RldPtrs.emplace_back(reinterpret_cast<uintptr_t>(I));
+      LLVM_DEBUG(dbgs() << "  --  RLD\n");
+      break;
+    case GOFF::RT_LEN:
+      LLVM_DEBUG(dbgs() << "  --  LEN (GOFF record type) unhandled\n");
+      break;
+    case GOFF::RT_END:
+      LLVM_DEBUG(dbgs() << "  --  END (GOFF record type) unhandled\n");
+      break;
+    case GOFF::RT_HDR:
+      LLVM_DEBUG(dbgs() << "  --  HDR (GOFF record type) unhandled\n");
+      break;
+    default:
+      llvm_unreachable("Unknown record type");
+    }
+  }
+
+  getRelocationData();
+}
+
+// SymbolRef
+const uint8_t *GOFFObjectFile::getSymbolEsdRecord(DataRefImpl Symb) const {
+  const uint8_t *EsdRecord =
+      reinterpret_cast<const uint8_t *>(EsdPtrs[Symb.d.a]);
+  return EsdRecord;
+}
+Expected<StringRef> GOFFObjectFile::getSymbolName(DataRefImpl Symb) const {
+  if (EsdNames.count(Symb.d.a))
+    return EsdNames[Symb.d.a];
+
+  const char *Record = (const char *)getSymbolEsdRecord(Symb);
+
+  // TODO: This could probably be changed to extract the length of the symbol
+  // name and then grab only that many characters but for now this works fine
+  uint16_t Continuations = 0;
+  while (true) {
+    // Is the record continued in the next record
+    const char *ContinuationByte =
+        Record + (Continuations * GOFF::RecordLength) + 1;
+    bool IsContinued = *ContinuationByte & 0x01;
+
+    if (IsContinued)
+      ++Continuations;
+    else
+      break;
+  }
+
+  SmallString<256> SymbolName(Record + 72, Record + GOFF::RecordLength);
+
+  // This assumes that we always emit 80 byte records even if the rest of the
+  // data in a record is nulls
+  for (uint16_t I = 0; I < Continuations; ++I) {
+    const char *ContRecord = Record + (GOFF::RecordLength * (I + 1));
+    SymbolName.append(ContRecord + 3, ContRecord + GOFF::RecordLength);
+  }
+
+  SmallString<256> SymbolNameConverted;
+  if (auto EC = Converter.convert(SymbolName, SymbolNameConverted))
+    return errorCodeToError(EC);
+  EsdNames[Symb.d.a].assign(SymbolNameConverted.c_str());
+  return EsdNames[Symb.d.a];
+}
+
+std::error_code GOFFObjectFile::getSymbolName(SymbolRef Symbol,
+                                              StringRef &Res) const {
+  Expected<StringRef> NameOrErr = getSymbolName(Symbol.getRawDataRefImpl());
+  if (NameOrErr) {
+    Res = *NameOrErr;
+    return std::error_code();
+  }
+  return errorToErrorCode(NameOrErr.takeError());
+}
+
+Expected<uint64_t> GOFFObjectFile::getSymbolAddress(DataRefImpl Symb) const {
+  uint32_t Offset;
+  const uint8_t *EsdRecord = getSymbolEsdRecord(Symb);
+  ESDRecord::getOffset(EsdRecord, Offset);
+  return static_cast<uint64_t>(Offset);
+}
+
+uint64_t GOFFObjectFile::getSymbolValueImpl(DataRefImpl Symb) const {
+  uint32_t Offset;
+  const uint8_t *EsdRecord = getSymbolEsdRecord(Symb);
+  ESDRecord::getOffset(EsdRecord, Offset);
+  return static_cast<uint64_t>(Offset);
+}
+
+uint64_t GOFFObjectFile::getCommonSymbolSizeImpl(DataRefImpl Symb) const {
+  return 0;
+}
+
+bool GOFFObjectFile::isSymbolUnresolved(DataRefImpl Symb) const {
+  const uint8_t *Record = getSymbolEsdRecord(Symb);
+  GOFF::ESDSymbolType SymbolType;
+  ESDRecord::getSymbolType(Record, SymbolType);
+
+  if (SymbolType == GOFF::ESD_ST_ExternalReference)
+    return true;
+  if (SymbolType == GOFF::ESD_ST_PartReference) {
+    uint32_t Length;
+    ESDRecord::getLength(Record, Length);
+    if (Length == 0)
+      return true;
+  }
+  return false;
+}
+
+bool GOFFObjectFile::isSymbolIndirect(DataRefImpl Symb) const {
+  const uint8_t *Record = getSymbolEsdRecord(Symb);
+  bool Indirect;
+  ESDRecord::getIndirectReference(Record, Indirect);
+  return Indirect;
+}
+
+Expected<uint32_t> GOFFObjectFile::getSymbolFlags(DataRefImpl Symb) const {
+  uint32_t Flags = 0;
+  if (isSymbolUnresolved(Symb))
+    Flags |= SymbolRef::SF_Undefined;
+
+  const uint8_t *Record = getSymbolEsdRecord(Symb);
+
+  GOFF::ESDBindingStrength BindingStrength;
+  ESDRecord::getBindingStrength(Record, BindingStrength);
+  if (BindingStrength == GOFF::ESD_BST_Weak)
+    Flags |= SymbolRef::SF_Weak;
+
+  GOFF::ESDBindingScope BindingScope;
+  ESDRecord::getBindingScope(Record, BindingScope);
+
+  if (BindingScope != GOFF::ESD_BSC_Section) {
+    Expected<StringRef> Name = getSymbolName(Symb);
+    if (Name && !Name->equals(" ")) { // blank name is local
+      Flags |= SymbolRef::SF_Global;
+      if (BindingScope == GOFF::ESD_BSC_ImportExport)
+        Flags |= SymbolRef::SF_Exported;
+      else if (!(Flags & SymbolRef::SF_Undefined))
+        Flags |= SymbolRef::SF_Hidden;
+    }
+  }
+
+  return Flags;
+}
+
+Expected<SymbolRef::Type>
+GOFFObjectFile::getSymbolType(DataRefImpl Symb) const {
+  const uint8_t *Record = getSymbolEsdRecord(Symb);
+  GOFF::ESDSymbolType SymbolType;
+  ESDRecord::getSymbolType(Record, SymbolType);
+  GOFF::ESDExecutable Executable;
+  ESDRecord::getExecutable(Record, Executable);
+
+  assert((SymbolType == GOFF::ESD_ST_SectionDefinition ||
+          SymbolType == GOFF::ESD_ST_ElementDefinition ||
+          SymbolType == GOFF::ESD_ST_LabelDefinition ||
+          SymbolType == GOFF::ESD_ST_PartReference ||
+          SymbolType == GOFF::ESD_ST_ExternalReference) &&
+         "SymbolType must be SectionDef/ElemDef/LabelDef/PartRef/ExtRef");
+
+  switch (SymbolType) {
+  case GOFF::ESD_ST_SectionDefinition:
+  case GOFF::ESD_ST_ElementDefinition:
+    return SymbolRef::ST_Other;
+  case GOFF::ESD_ST_LabelDefinition:
+  case GOFF::ESD_ST_PartReference:
+  case GOFF::ESD_ST_ExternalReference:
+    assert((Executable == GOFF::ESD_EXE_CODE ||
+            Executable == GOFF::ESD_EXE_DATA ||
+            Executable == GOFF::ESD_EXE_Unspecified) &&
+           "Executable must be CODE/DATA/Unspecified");
+    switch (Executable) {
+    case GOFF::ESD_EXE_CODE:
+      return SymbolRef::ST_Function;
+    case GOFF::ESD_EXE_DATA:
+      return SymbolRef::ST_Data;
+    case GOFF::ESD_EXE_Unspecified:
+      return SymbolRef::ST_Unknown;
+    }
+  }
+}
+
+Expected<section_iterator>
+GOFFObjectFile::getSymbolSection(DataRefImpl Symb) const {
+  DataRefImpl Sec;
+
+  if (isSymbolUnresolved(Symb))
+    return section_iterator(SectionRef(Sec, this));
+
+  const uint8_t *SymEsdRecord =
+      reinterpret_cast<const uint8_t *>(EsdPtrs[Symb.d.a]);
+  uint32_t SymEdId;
+  ESDRecord::getParentEsdId(SymEsdRecord, SymEdId);
+  const uint8_t *SymEdRecord =
+      reinterpret_cast<const uint8_t *>(EsdPtrs[SymEdId]);
+
+  for (size_t I = 0; I < SectionList.size(); ++I) {
+    bool Found;
+    const uint8_t *SectionPrRecord = getSectionPrEsdRecord(I);
+    if (SectionPrRecord) {
+      Found = SymEsdRecord == SectionPrRecord;
+    } else {
+      const uint8_t *SectionEdRecord = getSectionEdEsdRecord(I);
+      Found = SymEdRecord == SectionEdRecord;
+    }
+
+    if (Found) {
+      Sec.d.a = I;
+      return section_iterator(SectionRef(Sec, this));
+    }
+  }
+  llvm_unreachable("unable to get symbol section");
+  return section_iterator(SectionRef(Sec, this));
+}
+
+// SectionRef
+const uint8_t *GOFFObjectFile::getSectionEdEsdRecord(DataRefImpl &Sec) const {
+  SectionEntryImpl EsdIds = SectionList[Sec.d.a];
+  const uint8_t *EsdRecord =
+      reinterpret_cast<const uint8_t *>(EsdPtrs[EsdIds.d.a]);
+  return EsdRecord;
+}
+
+const uint8_t *GOFFObjectFile::getSectionPrEsdRecord(DataRefImpl &Sec) const {
+  SectionEntryImpl EsdIds = SectionList[Sec.d.a];
+  const uint8_t *EsdRecord = NULL;
+  if (EsdIds.d.b)
+    EsdRecord = reinterpret_cast<const uint8_t *>(EsdPtrs[EsdIds.d.b]);
+  return EsdRecord;
+}
+const uint8_t *
+GOFFObjectFile::getSectionEdEsdRecord(uint32_t SectionIndex) const {
+  DataRefImpl Sec;
+  Sec.d.a = SectionIndex;
+  const uint8_t *EsdRecord = getSectionEdEsdRecord(Sec);
+  return EsdRecord;
+}
+const uint8_t *
+GOFFObjectFile::getSectionPrEsdRecord(uint32_t SectionIndex) const {
+  DataRefImpl Sec;
+  Sec.d.a = SectionIndex;
+  const uint8_t *EsdRecord = getSectionPrEsdRecord(Sec);
+  return EsdRecord;
+}
+
+// RelocationRef
+void GOFFObjectFile::getRelocationData() {
+  if (RelocationData.size())
+    return;
+
+  // Calculate total length of relocation items from all records
+  uint32_t RelocationDataSize = 0;
+  uint16_t RldLengthField;
+  for (uint32_t I = 0; I < RldPtrs.size(); I++) {
+    const uint8_t *RldRecord = reinterpret_cast<const uint8_t *>(RldPtrs[I]);
+    RLDRecord::getLength(RldRecord, RldLengthField);
+    RelocationDataSize += RldLengthField;
+  }
+
+  RelocationData.reserve(RelocationDataSize);
+
+  // Populate RelocationData with relocation items from all records
+  for (uint32_t I = 0; I < RldPtrs.size(); I++) {
+    const uint8_t *RldRecord = reinterpret_cast<const uint8_t *>(RldPtrs[I]);
+    RLDRecord::getLength(RldRecord, RldLengthField);
+    uint16_t Remainder = RldLengthField;
+
+    uint32_t AppendLength = Remainder < (GOFF::RecordLength - 6)
+                                ? Remainder
+                                : (GOFF::RecordLength - 6);
+    const char *ChrPtr = reinterpret_cast<const char *>(RldRecord);
+    RelocationData.append(ChrPtr + 6, AppendLength); // copy from initial record
+    Remainder -= AppendLength;
+    ChrPtr += GOFF::RecordLength;
+    while (Remainder > 0) {
+      AppendLength = Remainder < (GOFF::RecordLength - 3)
+                         ? Remainder
+                         : (GOFF::RecordLength - 3);
+      RelocationData.append(ChrPtr + 3, AppendLength); // copy from continuation
+      Remainder -= AppendLength;
+      ChrPtr += GOFF::RecordLength;
+    }
+  }
+}
+
+// Utility routines which extract details about the relocation from
+// the relocation type.
+GOFF::RLDFetchStore GOFFObjectFile::getRLDFetchStore(uint64_t RelocationType) {
+  return (GOFF::RLDFetchStore)(RelocationType & 0x00000001);
+}
+GOFF::RLDAction GOFFObjectFile::getRLDAction(uint64_t RelocationType) {
+  return (GOFF::RLDAction)((RelocationType & 0x000000FE) >> 1);
+}
+uint8_t GOFFObjectFile::getRLDBitOffset(uint64_t RelocationType) {
+  return ((RelocationType & 0x00070000) >> 16);
+}
+uint16_t GOFFObjectFile::getRLDBitLength(uint64_t RelocationType) {
+  return ((RelocationType & 0xFFE00000) >> 21);
+}
+bool GOFFObjectFile::getRLDIsCodeAddressReference(uint64_t RelocationType) {
+  return (RelocationType & RLD_CODE_ADDR_FLAG) != 0;
+}
+bool GOFFObjectFile::getRLDSymbolIsIndirect(uint64_t RelocationType) {
+  return (RelocationType & RLD_INDIRECT_FLAG) != 0;
+}
+bool GOFFObjectFile::getRLDIsWeak(uint64_t RelocationType) {
+  return (RelocationType & RLD_WEAK_FLAG) != 0;
+}
+
+section_iterator GOFFObjectFile::section_begin() const {
+  DataRefImpl Sec;
+  moveSectionNext(Sec);
+  return section_iterator(SectionRef(Sec, this));
+}
+
+section_iterator GOFFObjectFile::section_end() const {
+  DataRefImpl Sec;
+  return section_iterator(SectionRef(Sec, this));
+}
+
+void GOFFObjectFile::moveSymbolNext(DataRefImpl &Symb) const {
+  for (uint32_t I = Symb.d.a + 1; I < EsdPtrs.size(); ++I) {
+    if (EsdPtrs[I]) {
+      const uint8_t *EsdRecord = reinterpret_cast<const uint8_t *>(EsdPtrs[I]);
+      GOFF::ESDSymbolType SymbolType;
+      ESDRecord::getSymbolType(EsdRecord, SymbolType);
+      // Skip EDs - i.e. section symbols
+      bool IgnoreSpecialGOFFSymbols = true;
+      bool SkipSymbol = ((SymbolType == GOFF::ESD_ST_ElementDefinition) ||
+                         (SymbolType == GOFF::ESD_ST_SectionDefinition)) &&
+                        IgnoreSpecialGOFFSymbols;
+      if (!SkipSymbol) {
+        Symb.d.a = I;
+        return;
+      }
+    }
+  }
+  Symb.d.a = 0; // symbol_end
+}
+
+basic_symbol_iterator GOFFObjectFile::symbol_begin() const {
+  DataRefImpl Symb;
+  moveSymbolNext(Symb);
+  return basic_symbol_iterator(SymbolRef(Symb, this));
+}
+
+basic_symbol_iterator GOFFObjectFile::symbol_end() const {
+  DataRefImpl Symb;
+  return basic_symbol_iterator(SymbolRef(Symb, this));
+}
diff --git a/llvm/lib/Object/ObjectFile.cpp b/llvm/lib/Object/ObjectFile.cpp
--- a/llvm/lib/Object/ObjectFile.cpp
+++ b/llvm/lib/Object/ObjectFile.cpp
@@ -126,6 +126,9 @@
     // XCOFF implies AIX.
     TheTriple.setOS(Triple::AIX);
     TheTriple.setObjectFormat(Triple::XCOFF);
+  } else if (isGOFF()) {
+    TheTriple.setOS(Triple::ZOS);
+    TheTriple.setObjectFormat(Triple::GOFF);
   }
 
   return TheTriple;
@@ -167,6 +170,8 @@
   case file_magic::macho_dsym_companion:
   case file_magic::macho_kext_bundle:
     return createMachOObjectFile(Object);
+  case file_magic::goff_object:
+    return createGOFFObjectFile(Object);
   case file_magic::coff_object:
   case file_magic::coff_import_library:
   case file_magic::pecoff_executable:
diff --git a/llvm/lib/Object/SymbolicFile.cpp b/llvm/lib/Object/SymbolicFile.cpp
--- a/llvm/lib/Object/SymbolicFile.cpp
+++ b/llvm/lib/Object/SymbolicFile.cpp
@@ -64,6 +64,7 @@
   case file_magic::macho_dsym_companion:
   case file_magic::macho_kext_bundle:
   case file_magic::pecoff_executable:
+  case file_magic::goff_object:
   case file_magic::xcoff_object_32:
   case file_magic::xcoff_object_64:
   case file_magic::wasm_object: