278 lines
		
	
	
		
			8.0 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			278 lines
		
	
	
		
			8.0 KiB
		
	
	
	
		
			C++
		
	
	
	
//===-- llvm/BinaryFormat/XCOFF.cpp - The XCOFF file format -----*- 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
 | 
						|
//
 | 
						|
//===----------------------------------------------------------------------===//
 | 
						|
 | 
						|
#include "llvm/BinaryFormat/XCOFF.h"
 | 
						|
#include "llvm/ADT/SmallString.h"
 | 
						|
#include "llvm/ADT/StringRef.h"
 | 
						|
#include "llvm/Support/Errc.h"
 | 
						|
#include "llvm/Support/Error.h"
 | 
						|
 | 
						|
using namespace llvm;
 | 
						|
 | 
						|
#define SMC_CASE(A)                                                            \
 | 
						|
  case XCOFF::XMC_##A:                                                         \
 | 
						|
    return #A;
 | 
						|
StringRef XCOFF::getMappingClassString(XCOFF::StorageMappingClass SMC) {
 | 
						|
  switch (SMC) {
 | 
						|
    SMC_CASE(PR)
 | 
						|
    SMC_CASE(RO)
 | 
						|
    SMC_CASE(DB)
 | 
						|
    SMC_CASE(GL)
 | 
						|
    SMC_CASE(XO)
 | 
						|
    SMC_CASE(SV)
 | 
						|
    SMC_CASE(SV64)
 | 
						|
    SMC_CASE(SV3264)
 | 
						|
    SMC_CASE(TI)
 | 
						|
    SMC_CASE(TB)
 | 
						|
    SMC_CASE(RW)
 | 
						|
    SMC_CASE(TC0)
 | 
						|
    SMC_CASE(TC)
 | 
						|
    SMC_CASE(TD)
 | 
						|
    SMC_CASE(DS)
 | 
						|
    SMC_CASE(UA)
 | 
						|
    SMC_CASE(BS)
 | 
						|
    SMC_CASE(UC)
 | 
						|
    SMC_CASE(TL)
 | 
						|
    SMC_CASE(UL)
 | 
						|
    SMC_CASE(TE)
 | 
						|
#undef SMC_CASE
 | 
						|
  }
 | 
						|
 | 
						|
  // TODO: need to add a test case for "Unknown" and other SMC.
 | 
						|
  return "Unknown";
 | 
						|
}
 | 
						|
 | 
						|
#define RELOC_CASE(A)                                                          \
 | 
						|
  case XCOFF::A:                                                               \
 | 
						|
    return #A;
 | 
						|
StringRef XCOFF::getRelocationTypeString(XCOFF::RelocationType Type) {
 | 
						|
  switch (Type) {
 | 
						|
    RELOC_CASE(R_POS)
 | 
						|
    RELOC_CASE(R_RL)
 | 
						|
    RELOC_CASE(R_RLA)
 | 
						|
    RELOC_CASE(R_NEG)
 | 
						|
    RELOC_CASE(R_REL)
 | 
						|
    RELOC_CASE(R_TOC)
 | 
						|
    RELOC_CASE(R_TRL)
 | 
						|
    RELOC_CASE(R_TRLA)
 | 
						|
    RELOC_CASE(R_GL)
 | 
						|
    RELOC_CASE(R_TCL)
 | 
						|
    RELOC_CASE(R_REF)
 | 
						|
    RELOC_CASE(R_BA)
 | 
						|
    RELOC_CASE(R_BR)
 | 
						|
    RELOC_CASE(R_RBA)
 | 
						|
    RELOC_CASE(R_RBR)
 | 
						|
    RELOC_CASE(R_TLS)
 | 
						|
    RELOC_CASE(R_TLS_IE)
 | 
						|
    RELOC_CASE(R_TLS_LD)
 | 
						|
    RELOC_CASE(R_TLS_LE)
 | 
						|
    RELOC_CASE(R_TLSM)
 | 
						|
    RELOC_CASE(R_TLSML)
 | 
						|
    RELOC_CASE(R_TOCU)
 | 
						|
    RELOC_CASE(R_TOCL)
 | 
						|
  }
 | 
						|
  return "Unknown";
 | 
						|
}
 | 
						|
#undef RELOC_CASE
 | 
						|
 | 
						|
#define LANG_CASE(A)                                                           \
 | 
						|
  case XCOFF::TracebackTable::A:                                               \
 | 
						|
    return #A;
 | 
						|
 | 
						|
StringRef XCOFF::getNameForTracebackTableLanguageId(
 | 
						|
    XCOFF::TracebackTable::LanguageID LangId) {
 | 
						|
  switch (LangId) {
 | 
						|
    LANG_CASE(C)
 | 
						|
    LANG_CASE(Fortran)
 | 
						|
    LANG_CASE(Pascal)
 | 
						|
    LANG_CASE(Ada)
 | 
						|
    LANG_CASE(PL1)
 | 
						|
    LANG_CASE(Basic)
 | 
						|
    LANG_CASE(Lisp)
 | 
						|
    LANG_CASE(Cobol)
 | 
						|
    LANG_CASE(Modula2)
 | 
						|
    LANG_CASE(Rpg)
 | 
						|
    LANG_CASE(PL8)
 | 
						|
    LANG_CASE(Assembly)
 | 
						|
    LANG_CASE(Java)
 | 
						|
    LANG_CASE(ObjectiveC)
 | 
						|
    LANG_CASE(CPlusPlus)
 | 
						|
  }
 | 
						|
  return "Unknown";
 | 
						|
}
 | 
						|
#undef LANG_CASE
 | 
						|
 | 
						|
Expected<SmallString<32>> XCOFF::parseParmsType(uint32_t Value,
 | 
						|
                                                unsigned FixedParmsNum,
 | 
						|
                                                unsigned FloatingParmsNum) {
 | 
						|
  SmallString<32> ParmsType;
 | 
						|
  int Bits = 0;
 | 
						|
  unsigned ParsedFixedNum = 0;
 | 
						|
  unsigned ParsedFloatingNum = 0;
 | 
						|
  unsigned ParsedNum = 0;
 | 
						|
  unsigned ParmsNum = FixedParmsNum + FloatingParmsNum;
 | 
						|
 | 
						|
  // In the function PPCFunctionInfo::getParmsType(), when there are no vector
 | 
						|
  // parameters, the 31st bit of ParmsType is always zero even if it indicates a
 | 
						|
  // floating point parameter. The parameter type information is lost. There
 | 
						|
  // are only 8 GPRs used for parameters passing, the floating parameters
 | 
						|
  // also occupy GPRs if there are available, so the 31st bit can never be a
 | 
						|
  // fixed parameter. At the same time, we also do not know whether the zero of
 | 
						|
  // the 31st bit indicates a float or double parameter type here. Therefore, we
 | 
						|
  // ignore the 31st bit.
 | 
						|
  while (Bits < 31 && ParsedNum < ParmsNum) {
 | 
						|
    if (++ParsedNum > 1)
 | 
						|
      ParmsType += ", ";
 | 
						|
    if ((Value & TracebackTable::ParmTypeIsFloatingBit) == 0) {
 | 
						|
      // Fixed parameter type.
 | 
						|
      ParmsType += "i";
 | 
						|
      ++ParsedFixedNum;
 | 
						|
      Value <<= 1;
 | 
						|
      ++Bits;
 | 
						|
    } else {
 | 
						|
      if ((Value & TracebackTable::ParmTypeFloatingIsDoubleBit) == 0)
 | 
						|
        // Float parameter type.
 | 
						|
        ParmsType += "f";
 | 
						|
      else
 | 
						|
        // Double parameter type.
 | 
						|
        ParmsType += "d";
 | 
						|
      ++ParsedFloatingNum;
 | 
						|
      Value <<= 2;
 | 
						|
      Bits += 2;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  // We have more parameters than the 32 Bits could encode.
 | 
						|
  if (ParsedNum < ParmsNum)
 | 
						|
    ParmsType += ", ...";
 | 
						|
 | 
						|
  if (Value != 0u || ParsedFixedNum > FixedParmsNum ||
 | 
						|
      ParsedFloatingNum > FloatingParmsNum)
 | 
						|
    return createStringError(errc::invalid_argument,
 | 
						|
                             "ParmsType encodes can not map to ParmsNum "
 | 
						|
                             "parameters in parseParmsType.");
 | 
						|
  return ParmsType;
 | 
						|
}
 | 
						|
 | 
						|
SmallString<32> XCOFF::getExtendedTBTableFlagString(uint8_t Flag) {
 | 
						|
  SmallString<32> Res;
 | 
						|
 | 
						|
  if (Flag & ExtendedTBTableFlag::TB_OS1)
 | 
						|
    Res += "TB_OS1 ";
 | 
						|
  if (Flag & ExtendedTBTableFlag::TB_RESERVED)
 | 
						|
    Res += "TB_RESERVED ";
 | 
						|
  if (Flag & ExtendedTBTableFlag::TB_SSP_CANARY)
 | 
						|
    Res += "TB_SSP_CANARY ";
 | 
						|
  if (Flag & ExtendedTBTableFlag::TB_OS2)
 | 
						|
    Res += "TB_OS2 ";
 | 
						|
  if (Flag & ExtendedTBTableFlag::TB_EH_INFO)
 | 
						|
    Res += "TB_EH_INFO ";
 | 
						|
  if (Flag & ExtendedTBTableFlag::TB_LONGTBTABLE2)
 | 
						|
    Res += "TB_LONGTBTABLE2 ";
 | 
						|
 | 
						|
  // Two of the bits that haven't got used in the mask.
 | 
						|
  if (Flag & 0x06)
 | 
						|
    Res += "Unknown ";
 | 
						|
 | 
						|
  // Pop the last space.
 | 
						|
  Res.pop_back();
 | 
						|
  return Res;
 | 
						|
}
 | 
						|
 | 
						|
Expected<SmallString<32>>
 | 
						|
XCOFF::parseParmsTypeWithVecInfo(uint32_t Value, unsigned FixedParmsNum,
 | 
						|
                                 unsigned FloatingParmsNum,
 | 
						|
                                 unsigned VectorParmsNum) {
 | 
						|
  SmallString<32> ParmsType;
 | 
						|
 | 
						|
  unsigned ParsedFixedNum = 0;
 | 
						|
  unsigned ParsedFloatingNum = 0;
 | 
						|
  unsigned ParsedVectorNum = 0;
 | 
						|
  unsigned ParsedNum = 0;
 | 
						|
  unsigned ParmsNum = FixedParmsNum + FloatingParmsNum + VectorParmsNum;
 | 
						|
 | 
						|
  for (int Bits = 0; Bits < 32 && ParsedNum < ParmsNum; Bits += 2) {
 | 
						|
    if (++ParsedNum > 1)
 | 
						|
      ParmsType += ", ";
 | 
						|
 | 
						|
    switch (Value & TracebackTable::ParmTypeMask) {
 | 
						|
    case TracebackTable::ParmTypeIsFixedBits:
 | 
						|
      ParmsType += "i";
 | 
						|
      ++ParsedFixedNum;
 | 
						|
      break;
 | 
						|
    case TracebackTable::ParmTypeIsVectorBits:
 | 
						|
      ParmsType += "v";
 | 
						|
      ++ParsedVectorNum;
 | 
						|
      break;
 | 
						|
    case TracebackTable::ParmTypeIsFloatingBits:
 | 
						|
      ParmsType += "f";
 | 
						|
      ++ParsedFloatingNum;
 | 
						|
      break;
 | 
						|
    case TracebackTable::ParmTypeIsDoubleBits:
 | 
						|
      ParmsType += "d";
 | 
						|
      ++ParsedFloatingNum;
 | 
						|
      break;
 | 
						|
    default:
 | 
						|
      assert(false && "Unrecognized bits in ParmsType.");
 | 
						|
    }
 | 
						|
    Value <<= 2;
 | 
						|
  }
 | 
						|
 | 
						|
  // We have more parameters than the 32 Bits could encode.
 | 
						|
  if (ParsedNum < ParmsNum)
 | 
						|
    ParmsType += ", ...";
 | 
						|
 | 
						|
  if (Value != 0u || ParsedFixedNum > FixedParmsNum ||
 | 
						|
      ParsedFloatingNum > FloatingParmsNum || ParsedVectorNum > VectorParmsNum)
 | 
						|
    return createStringError(
 | 
						|
        errc::invalid_argument,
 | 
						|
        "ParmsType encodes can not map to ParmsNum parameters "
 | 
						|
        "in parseParmsTypeWithVecInfo.");
 | 
						|
 | 
						|
  return ParmsType;
 | 
						|
}
 | 
						|
 | 
						|
Expected<SmallString<32>> XCOFF::parseVectorParmsType(uint32_t Value,
 | 
						|
                                                      unsigned ParmsNum) {
 | 
						|
  SmallString<32> ParmsType;
 | 
						|
  unsigned ParsedNum = 0;
 | 
						|
  for (int Bits = 0; ParsedNum < ParmsNum && Bits < 32; Bits += 2) {
 | 
						|
    if (++ParsedNum > 1)
 | 
						|
      ParmsType += ", ";
 | 
						|
    switch (Value & TracebackTable::ParmTypeMask) {
 | 
						|
    case TracebackTable::ParmTypeIsVectorCharBit:
 | 
						|
      ParmsType += "vc";
 | 
						|
      break;
 | 
						|
 | 
						|
    case TracebackTable::ParmTypeIsVectorShortBit:
 | 
						|
      ParmsType += "vs";
 | 
						|
      break;
 | 
						|
 | 
						|
    case TracebackTable::ParmTypeIsVectorIntBit:
 | 
						|
      ParmsType += "vi";
 | 
						|
      break;
 | 
						|
 | 
						|
    case TracebackTable::ParmTypeIsVectorFloatBit:
 | 
						|
      ParmsType += "vf";
 | 
						|
      break;
 | 
						|
    }
 | 
						|
 | 
						|
    Value <<= 2;
 | 
						|
  }
 | 
						|
 | 
						|
  // We have more parameters than the 32 Bits could encode.
 | 
						|
  if (ParsedNum < ParmsNum)
 | 
						|
    ParmsType += ", ...";
 | 
						|
 | 
						|
  if (Value != 0u)
 | 
						|
    return createStringError(errc::invalid_argument,
 | 
						|
                             "ParmsType encodes more than ParmsNum parameters "
 | 
						|
                             "in parseVectorParmsType.");
 | 
						|
  return ParmsType;
 | 
						|
}
 |