clang 20.0.0 (based on r547379) from build 12806354. Bug: http://b/379133546 Test: N/A Change-Id: I2eb8938af55d809de674be63cb30cf27e801862b Upstream-Commit: ad834e67b1105d15ef907f6255d4c96e8e733f57
304 lines
9.2 KiB
C++
304 lines
9.2 KiB
C++
//===- GOFF.h - GOFF object file implementation -----------------*- 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 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/SmallString.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 {
|
|
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 {
|
|
public:
|
|
static Error getContinuousData(const uint8_t *Record, uint16_t DataLength,
|
|
int DataIndex, SmallString<256> &CompleteData);
|
|
|
|
static bool isContinued(const uint8_t *Record) {
|
|
uint8_t IsContinued;
|
|
getBits(Record, 1, 7, 1, IsContinued);
|
|
return IsContinued;
|
|
}
|
|
|
|
static bool isContinuation(const uint8_t *Record) {
|
|
uint8_t IsContinuation;
|
|
getBits(Record, 1, 6, 1, IsContinuation);
|
|
return IsContinuation;
|
|
}
|
|
|
|
protected:
|
|
/// \brief Get 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 value of bit field.
|
|
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);
|
|
Value = (Value >> (8 - BitIndex - Length)) & ((1 << Length) - 1);
|
|
}
|
|
|
|
template <class T>
|
|
static void get(const uint8_t *Bytes, uint8_t ByteIndex, T &Value) {
|
|
assert(ByteIndex + sizeof(T) <= GOFF::RecordLength &&
|
|
"Byte index out of bounds!");
|
|
Value = support::endian::read<T, llvm::endianness::big>(&Bytes[ByteIndex]);
|
|
}
|
|
};
|
|
|
|
class TXTRecord : public Record {
|
|
public:
|
|
/// \brief Maximum length of data; any more must go in continuation.
|
|
static const uint8_t TXTMaxDataLength = 56;
|
|
|
|
static Error getData(const uint8_t *Record, SmallString<256> &CompleteData);
|
|
|
|
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 HDRRecord : public Record {
|
|
public:
|
|
static Error getData(const uint8_t *Record, SmallString<256> &CompleteData);
|
|
|
|
static uint16_t getPropertyModuleLength(const uint8_t *Record) {
|
|
uint16_t Length;
|
|
get<uint16_t>(Record, 52, Length);
|
|
return 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 ESDMaxUncontinuedNameLength = 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:
|
|
static Error getData(const uint8_t *Record, SmallString<256> &CompleteData);
|
|
|
|
// 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;
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
static uint16_t getNameLength(const uint8_t *Record) {
|
|
uint16_t Length;
|
|
get<uint16_t>(Record, 70, Length);
|
|
return Length;
|
|
}
|
|
};
|
|
|
|
class ENDRecord : public Record {
|
|
public:
|
|
static Error getData(const uint8_t *Record, SmallString<256> &CompleteData);
|
|
|
|
static uint16_t getNameLength(const uint8_t *Record) {
|
|
uint16_t Length;
|
|
get<uint16_t>(Record, 24, Length);
|
|
return Length;
|
|
}
|
|
};
|
|
|
|
} // end namespace object
|
|
} // end namespace llvm
|
|
|
|
#endif
|