| //===- bolt/Core/Relocation.cpp - Object file relocations -----------------===// | |
| // | |
| // 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 implements the Relocation class. | |
| // | |
| //===----------------------------------------------------------------------===// | |
| #include "bolt/Core/Relocation.h" | |
| #include "llvm/MC/MCContext.h" | |
| #include "llvm/MC/MCExpr.h" | |
| #include "llvm/MC/MCStreamer.h" | |
| #include "llvm/MC/MCSymbol.h" | |
| #include "llvm/Object/ELF.h" | |
| #include "llvm/Object/ObjectFile.h" | |
| using namespace llvm; | |
| using namespace bolt; | |
| namespace ELFReserved { | |
| enum { | |
| R_RISCV_TPREL_I = 49, | |
| R_RISCV_TPREL_S = 50, | |
| }; | |
| } // namespace ELFReserved | |
| Triple::ArchType Relocation::Arch; | |
| static bool isSupportedX86(uint32_t Type) { | |
| switch (Type) { | |
| default: | |
| return false; | |
| case ELF::R_X86_64_8: | |
| case ELF::R_X86_64_16: | |
| case ELF::R_X86_64_32: | |
| case ELF::R_X86_64_32S: | |
| case ELF::R_X86_64_64: | |
| case ELF::R_X86_64_PC8: | |
| case ELF::R_X86_64_PC32: | |
| case ELF::R_X86_64_PC64: | |
| case ELF::R_X86_64_PLT32: | |
| case ELF::R_X86_64_GOTPC64: | |
| case ELF::R_X86_64_GOTPCREL: | |
| case ELF::R_X86_64_GOTTPOFF: | |
| case ELF::R_X86_64_TPOFF32: | |
| case ELF::R_X86_64_GOTPCRELX: | |
| case ELF::R_X86_64_REX_GOTPCRELX: | |
| return true; | |
| } | |
| } | |
| static bool isSupportedAArch64(uint32_t Type) { | |
| switch (Type) { | |
| default: | |
| return false; | |
| case ELF::R_AARCH64_CALL26: | |
| case ELF::R_AARCH64_JUMP26: | |
| case ELF::R_AARCH64_TSTBR14: | |
| case ELF::R_AARCH64_CONDBR19: | |
| case ELF::R_AARCH64_ADR_PREL_LO21: | |
| case ELF::R_AARCH64_ADR_PREL_PG_HI21: | |
| case ELF::R_AARCH64_ADR_PREL_PG_HI21_NC: | |
| case ELF::R_AARCH64_LDST64_ABS_LO12_NC: | |
| case ELF::R_AARCH64_ADD_ABS_LO12_NC: | |
| case ELF::R_AARCH64_LDST128_ABS_LO12_NC: | |
| case ELF::R_AARCH64_LDST32_ABS_LO12_NC: | |
| case ELF::R_AARCH64_LDST16_ABS_LO12_NC: | |
| case ELF::R_AARCH64_LDST8_ABS_LO12_NC: | |
| case ELF::R_AARCH64_ADR_GOT_PAGE: | |
| case ELF::R_AARCH64_TLSGD_ADR_PAGE21: | |
| case ELF::R_AARCH64_TLSGD_ADD_LO12_NC: | |
| case ELF::R_AARCH64_TLSDESC_ADR_PREL21: | |
| case ELF::R_AARCH64_TLSDESC_ADR_PAGE21: | |
| case ELF::R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC: | |
| case ELF::R_AARCH64_TLSLE_ADD_TPREL_HI12: | |
| case ELF::R_AARCH64_TLSLE_ADD_TPREL_LO12_NC: | |
| case ELF::R_AARCH64_TLSLE_MOVW_TPREL_G0: | |
| case ELF::R_AARCH64_TLSLE_MOVW_TPREL_G0_NC: | |
| case ELF::R_AARCH64_LD64_GOT_LO12_NC: | |
| case ELF::R_AARCH64_TLSDESC_LD64_LO12: | |
| case ELF::R_AARCH64_TLSDESC_ADD_LO12: | |
| case ELF::R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21: | |
| case ELF::R_AARCH64_PREL16: | |
| case ELF::R_AARCH64_PREL32: | |
| case ELF::R_AARCH64_PREL64: | |
| case ELF::R_AARCH64_ABS16: | |
| case ELF::R_AARCH64_ABS32: | |
| case ELF::R_AARCH64_ABS64: | |
| case ELF::R_AARCH64_MOVW_UABS_G0: | |
| case ELF::R_AARCH64_MOVW_UABS_G0_NC: | |
| case ELF::R_AARCH64_MOVW_UABS_G1: | |
| case ELF::R_AARCH64_MOVW_UABS_G1_NC: | |
| case ELF::R_AARCH64_MOVW_UABS_G2: | |
| case ELF::R_AARCH64_MOVW_UABS_G2_NC: | |
| case ELF::R_AARCH64_MOVW_UABS_G3: | |
| case ELF::R_AARCH64_PLT32: | |
| return true; | |
| } | |
| } | |
| static bool isSupportedRISCV(uint32_t Type) { | |
| switch (Type) { | |
| default: | |
| return false; | |
| case ELF::R_RISCV_JAL: | |
| case ELF::R_RISCV_CALL: | |
| case ELF::R_RISCV_CALL_PLT: | |
| case ELF::R_RISCV_BRANCH: | |
| case ELF::R_RISCV_RELAX: | |
| case ELF::R_RISCV_GOT_HI20: | |
| case ELF::R_RISCV_PCREL_HI20: | |
| case ELF::R_RISCV_PCREL_LO12_I: | |
| case ELF::R_RISCV_PCREL_LO12_S: | |
| case ELF::R_RISCV_RVC_JUMP: | |
| case ELF::R_RISCV_RVC_BRANCH: | |
| case ELF::R_RISCV_ADD32: | |
| case ELF::R_RISCV_SUB32: | |
| case ELF::R_RISCV_HI20: | |
| case ELF::R_RISCV_LO12_I: | |
| case ELF::R_RISCV_LO12_S: | |
| case ELF::R_RISCV_32: | |
| case ELF::R_RISCV_64: | |
| case ELF::R_RISCV_TLS_GOT_HI20: | |
| case ELF::R_RISCV_TLS_GD_HI20: | |
| case ELF::R_RISCV_TPREL_HI20: | |
| case ELF::R_RISCV_TPREL_ADD: | |
| case ELF::R_RISCV_TPREL_LO12_I: | |
| case ELF::R_RISCV_TPREL_LO12_S: | |
| case ELFReserved::R_RISCV_TPREL_I: | |
| case ELFReserved::R_RISCV_TPREL_S: | |
| return true; | |
| } | |
| } | |
| static size_t getSizeForTypeX86(uint32_t Type) { | |
| switch (Type) { | |
| default: | |
| errs() << object::getELFRelocationTypeName(ELF::EM_X86_64, Type) << '\n'; | |
| llvm_unreachable("unsupported relocation type"); | |
| case ELF::R_X86_64_8: | |
| case ELF::R_X86_64_PC8: | |
| return 1; | |
| case ELF::R_X86_64_16: | |
| return 2; | |
| case ELF::R_X86_64_PLT32: | |
| case ELF::R_X86_64_PC32: | |
| case ELF::R_X86_64_32S: | |
| case ELF::R_X86_64_32: | |
| case ELF::R_X86_64_GOTPCREL: | |
| case ELF::R_X86_64_GOTTPOFF: | |
| case ELF::R_X86_64_TPOFF32: | |
| case ELF::R_X86_64_GOTPCRELX: | |
| case ELF::R_X86_64_REX_GOTPCRELX: | |
| return 4; | |
| case ELF::R_X86_64_PC64: | |
| case ELF::R_X86_64_64: | |
| case ELF::R_X86_64_GOTPC64: | |
| return 8; | |
| } | |
| } | |
| static size_t getSizeForTypeAArch64(uint32_t Type) { | |
| switch (Type) { | |
| default: | |
| errs() << object::getELFRelocationTypeName(ELF::EM_AARCH64, Type) << '\n'; | |
| llvm_unreachable("unsupported relocation type"); | |
| case ELF::R_AARCH64_ABS16: | |
| case ELF::R_AARCH64_PREL16: | |
| return 2; | |
| case ELF::R_AARCH64_CALL26: | |
| case ELF::R_AARCH64_JUMP26: | |
| case ELF::R_AARCH64_TSTBR14: | |
| case ELF::R_AARCH64_CONDBR19: | |
| case ELF::R_AARCH64_ADR_PREL_LO21: | |
| case ELF::R_AARCH64_ADR_PREL_PG_HI21: | |
| case ELF::R_AARCH64_ADR_PREL_PG_HI21_NC: | |
| case ELF::R_AARCH64_LDST64_ABS_LO12_NC: | |
| case ELF::R_AARCH64_ADD_ABS_LO12_NC: | |
| case ELF::R_AARCH64_LDST128_ABS_LO12_NC: | |
| case ELF::R_AARCH64_LDST32_ABS_LO12_NC: | |
| case ELF::R_AARCH64_LDST16_ABS_LO12_NC: | |
| case ELF::R_AARCH64_LDST8_ABS_LO12_NC: | |
| case ELF::R_AARCH64_ADR_GOT_PAGE: | |
| case ELF::R_AARCH64_TLSGD_ADR_PAGE21: | |
| case ELF::R_AARCH64_TLSGD_ADD_LO12_NC: | |
| case ELF::R_AARCH64_TLSDESC_ADR_PREL21: | |
| case ELF::R_AARCH64_TLSDESC_ADR_PAGE21: | |
| case ELF::R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC: | |
| case ELF::R_AARCH64_TLSLE_ADD_TPREL_HI12: | |
| case ELF::R_AARCH64_TLSLE_ADD_TPREL_LO12_NC: | |
| case ELF::R_AARCH64_TLSLE_MOVW_TPREL_G0: | |
| case ELF::R_AARCH64_TLSLE_MOVW_TPREL_G0_NC: | |
| case ELF::R_AARCH64_LD64_GOT_LO12_NC: | |
| case ELF::R_AARCH64_TLSDESC_LD64_LO12: | |
| case ELF::R_AARCH64_TLSDESC_ADD_LO12: | |
| case ELF::R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21: | |
| case ELF::R_AARCH64_PREL32: | |
| case ELF::R_AARCH64_MOVW_UABS_G0: | |
| case ELF::R_AARCH64_MOVW_UABS_G0_NC: | |
| case ELF::R_AARCH64_MOVW_UABS_G1: | |
| case ELF::R_AARCH64_MOVW_UABS_G1_NC: | |
| case ELF::R_AARCH64_MOVW_UABS_G2: | |
| case ELF::R_AARCH64_MOVW_UABS_G2_NC: | |
| case ELF::R_AARCH64_MOVW_UABS_G3: | |
| case ELF::R_AARCH64_ABS32: | |
| case ELF::R_AARCH64_PLT32: | |
| return 4; | |
| case ELF::R_AARCH64_ABS64: | |
| case ELF::R_AARCH64_PREL64: | |
| return 8; | |
| } | |
| } | |
| static size_t getSizeForTypeRISCV(uint32_t Type) { | |
| switch (Type) { | |
| default: | |
| errs() << object::getELFRelocationTypeName(ELF::EM_RISCV, Type) << '\n'; | |
| llvm_unreachable("unsupported relocation type"); | |
| case ELF::R_RISCV_RVC_JUMP: | |
| case ELF::R_RISCV_RVC_BRANCH: | |
| return 2; | |
| case ELF::R_RISCV_JAL: | |
| case ELF::R_RISCV_BRANCH: | |
| case ELF::R_RISCV_PCREL_HI20: | |
| case ELF::R_RISCV_PCREL_LO12_I: | |
| case ELF::R_RISCV_PCREL_LO12_S: | |
| case ELF::R_RISCV_32_PCREL: | |
| case ELF::R_RISCV_ADD32: | |
| case ELF::R_RISCV_SUB32: | |
| case ELF::R_RISCV_HI20: | |
| case ELF::R_RISCV_LO12_I: | |
| case ELF::R_RISCV_LO12_S: | |
| case ELF::R_RISCV_32: | |
| return 4; | |
| case ELF::R_RISCV_64: | |
| case ELF::R_RISCV_CALL: | |
| case ELF::R_RISCV_CALL_PLT: | |
| case ELF::R_RISCV_GOT_HI20: | |
| case ELF::R_RISCV_TLS_GOT_HI20: | |
| case ELF::R_RISCV_TLS_GD_HI20: | |
| // See extractValueRISCV for why this is necessary. | |
| return 8; | |
| } | |
| } | |
| static bool skipRelocationTypeX86(uint32_t Type) { | |
| return Type == ELF::R_X86_64_NONE; | |
| } | |
| static bool skipRelocationTypeAArch64(uint32_t Type) { | |
| switch (Type) { | |
| default: | |
| return false; | |
| case ELF::R_AARCH64_NONE: | |
| case ELF::R_AARCH64_LD_PREL_LO19: | |
| case ELF::R_AARCH64_TLSDESC_CALL: | |
| return true; | |
| } | |
| } | |
| static bool skipRelocationTypeRISCV(uint32_t Type) { | |
| switch (Type) { | |
| default: | |
| return false; | |
| case ELF::R_RISCV_NONE: | |
| case ELF::R_RISCV_RELAX: | |
| return true; | |
| } | |
| } | |
| static uint64_t encodeValueX86(uint32_t Type, uint64_t Value, uint64_t PC) { | |
| switch (Type) { | |
| default: | |
| llvm_unreachable("unsupported relocation"); | |
| case ELF::R_X86_64_64: | |
| case ELF::R_X86_64_32: | |
| break; | |
| case ELF::R_X86_64_PC32: | |
| Value -= PC; | |
| break; | |
| } | |
| return Value; | |
| } | |
| static bool canEncodeValueAArch64(uint32_t Type, uint64_t Value, uint64_t PC) { | |
| switch (Type) { | |
| default: | |
| llvm_unreachable("unsupported relocation"); | |
| case ELF::R_AARCH64_CALL26: | |
| case ELF::R_AARCH64_JUMP26: | |
| return isInt<28>(Value - PC); | |
| } | |
| } | |
| static uint64_t encodeValueAArch64(uint32_t Type, uint64_t Value, uint64_t PC) { | |
| switch (Type) { | |
| default: | |
| llvm_unreachable("unsupported relocation"); | |
| case ELF::R_AARCH64_ABS16: | |
| case ELF::R_AARCH64_ABS32: | |
| case ELF::R_AARCH64_ABS64: | |
| break; | |
| case ELF::R_AARCH64_PREL16: | |
| case ELF::R_AARCH64_PREL32: | |
| case ELF::R_AARCH64_PREL64: | |
| Value -= PC; | |
| break; | |
| case ELF::R_AARCH64_CALL26: | |
| Value -= PC; | |
| assert(isInt<28>(Value) && "only PC +/- 128MB is allowed for direct call"); | |
| // Immediate goes in bits 25:0 of BL. | |
| // OP 1001_01 goes in bits 31:26 of BL. | |
| Value = ((Value >> 2) & 0x3ffffff) | 0x94000000ULL; | |
| break; | |
| case ELF::R_AARCH64_JUMP26: | |
| Value -= PC; | |
| assert(isInt<28>(Value) && | |
| "only PC +/- 128MB is allowed for direct branch"); | |
| // Immediate goes in bits 25:0 of B. | |
| // OP 0001_01 goes in bits 31:26 of B. | |
| Value = ((Value >> 2) & 0x3ffffff) | 0x14000000ULL; | |
| break; | |
| } | |
| return Value; | |
| } | |
| static uint64_t canEncodeValueRISCV(uint32_t Type, uint64_t Value, | |
| uint64_t PC) { | |
| switch (Type) { | |
| default: | |
| llvm_unreachable("unsupported relocation"); | |
| case ELF::R_RISCV_32: | |
| case ELF::R_RISCV_64: | |
| return true; | |
| } | |
| } | |
| static uint64_t encodeValueRISCV(uint32_t Type, uint64_t Value, uint64_t PC) { | |
| switch (Type) { | |
| default: | |
| llvm_unreachable("unsupported relocation"); | |
| case ELF::R_RISCV_32: | |
| case ELF::R_RISCV_64: | |
| break; | |
| } | |
| return Value; | |
| } | |
| static uint64_t extractValueX86(uint32_t Type, uint64_t Contents, uint64_t PC) { | |
| if (Type == ELF::R_X86_64_32S) | |
| return SignExtend64<32>(Contents); | |
| if (Relocation::isPCRelative(Type)) | |
| return SignExtend64(Contents, 8 * Relocation::getSizeForType(Type)); | |
| return Contents; | |
| } | |
| static uint64_t extractValueAArch64(uint32_t Type, uint64_t Contents, | |
| uint64_t PC) { | |
| switch (Type) { | |
| default: | |
| errs() << object::getELFRelocationTypeName(ELF::EM_AARCH64, Type) << '\n'; | |
| llvm_unreachable("unsupported relocation type"); | |
| case ELF::R_AARCH64_ABS16: | |
| case ELF::R_AARCH64_ABS32: | |
| case ELF::R_AARCH64_ABS64: | |
| return Contents; | |
| case ELF::R_AARCH64_PREL16: | |
| return static_cast<int64_t>(PC) + SignExtend64<16>(Contents & 0xffff); | |
| case ELF::R_AARCH64_PREL32: | |
| case ELF::R_AARCH64_PLT32: | |
| return static_cast<int64_t>(PC) + SignExtend64<32>(Contents & 0xffffffff); | |
| case ELF::R_AARCH64_PREL64: | |
| return static_cast<int64_t>(PC) + Contents; | |
| case ELF::R_AARCH64_JUMP26: | |
| case ELF::R_AARCH64_CALL26: | |
| // Immediate goes in bits 25:0 of B and BL. | |
| Contents &= ~0xfffffffffc000000ULL; | |
| return static_cast<int64_t>(PC) + SignExtend64<28>(Contents << 2); | |
| case ELF::R_AARCH64_TSTBR14: | |
| // Immediate:15:2 goes in bits 18:5 of TBZ, TBNZ | |
| Contents &= ~0xfffffffffff8001fULL; | |
| return static_cast<int64_t>(PC) + SignExtend64<16>(Contents >> 3); | |
| case ELF::R_AARCH64_CONDBR19: | |
| // Immediate:20:2 goes in bits 23:5 of Bcc, CBZ, CBNZ | |
| Contents &= ~0xffffffffff00001fULL; | |
| return static_cast<int64_t>(PC) + SignExtend64<21>(Contents >> 3); | |
| case ELF::R_AARCH64_ADR_GOT_PAGE: | |
| case ELF::R_AARCH64_TLSGD_ADR_PAGE21: | |
| case ELF::R_AARCH64_TLSDESC_ADR_PREL21: | |
| case ELF::R_AARCH64_TLSDESC_ADR_PAGE21: | |
| case ELF::R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21: | |
| case ELF::R_AARCH64_ADR_PREL_LO21: | |
| case ELF::R_AARCH64_ADR_PREL_PG_HI21: | |
| case ELF::R_AARCH64_ADR_PREL_PG_HI21_NC: { | |
| // Bits 32:12 of Symbol address goes in bits 30:29 + 23:5 of ADRP | |
| // and ADR instructions | |
| bool IsAdr = !!(((Contents >> 31) & 0x1) == 0); | |
| Contents &= ~0xffffffff9f00001fUll; | |
| uint64_t LowBits = (Contents >> 29) & 0x3; | |
| uint64_t HighBits = (Contents >> 5) & 0x7ffff; | |
| Contents = LowBits | (HighBits << 2); | |
| if (IsAdr) | |
| return static_cast<int64_t>(PC) + SignExtend64<21>(Contents); | |
| // ADRP instruction | |
| Contents = static_cast<int64_t>(PC) + SignExtend64<33>(Contents << 12); | |
| Contents &= ~0xfffUll; | |
| return Contents; | |
| } | |
| case ELF::R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC: | |
| case ELF::R_AARCH64_TLSDESC_LD64_LO12: | |
| case ELF::R_AARCH64_LD64_GOT_LO12_NC: | |
| case ELF::R_AARCH64_LDST64_ABS_LO12_NC: { | |
| // Immediate goes in bits 21:10 of LD/ST instruction, taken | |
| // from bits 11:3 of Symbol address | |
| Contents &= ~0xffffffffffc003ffU; | |
| return Contents >> (10 - 3); | |
| } | |
| case ELF::R_AARCH64_TLSLE_ADD_TPREL_HI12: | |
| case ELF::R_AARCH64_TLSLE_ADD_TPREL_LO12_NC: | |
| case ELF::R_AARCH64_TLSGD_ADD_LO12_NC: | |
| case ELF::R_AARCH64_TLSDESC_ADD_LO12: | |
| case ELF::R_AARCH64_ADD_ABS_LO12_NC: { | |
| // Immediate goes in bits 21:10 of ADD instruction | |
| Contents &= ~0xffffffffffc003ffU; | |
| return Contents >> (10 - 0); | |
| } | |
| case ELF::R_AARCH64_LDST128_ABS_LO12_NC: { | |
| // Immediate goes in bits 21:10 of ADD instruction, taken | |
| // from bits 11:4 of Symbol address | |
| Contents &= ~0xffffffffffc003ffU; | |
| return Contents >> (10 - 4); | |
| } | |
| case ELF::R_AARCH64_LDST32_ABS_LO12_NC: { | |
| // Immediate goes in bits 21:10 of ADD instruction, taken | |
| // from bits 11:2 of Symbol address | |
| Contents &= ~0xffffffffffc003ffU; | |
| return Contents >> (10 - 2); | |
| } | |
| case ELF::R_AARCH64_LDST16_ABS_LO12_NC: { | |
| // Immediate goes in bits 21:10 of ADD instruction, taken | |
| // from bits 11:1 of Symbol address | |
| Contents &= ~0xffffffffffc003ffU; | |
| return Contents >> (10 - 1); | |
| } | |
| case ELF::R_AARCH64_LDST8_ABS_LO12_NC: { | |
| // Immediate goes in bits 21:10 of ADD instruction, taken | |
| // from bits 11:0 of Symbol address | |
| Contents &= ~0xffffffffffc003ffU; | |
| return Contents >> (10 - 0); | |
| } | |
| case ELF::R_AARCH64_MOVW_UABS_G3: | |
| case ELF::R_AARCH64_MOVW_UABS_G2_NC: | |
| case ELF::R_AARCH64_MOVW_UABS_G2: | |
| case ELF::R_AARCH64_MOVW_UABS_G1_NC: | |
| case ELF::R_AARCH64_MOVW_UABS_G1: | |
| case ELF::R_AARCH64_MOVW_UABS_G0_NC: | |
| case ELF::R_AARCH64_MOVW_UABS_G0: | |
| // The shift goes in bits 22:21 of MOV* instructions | |
| uint8_t Shift = (Contents >> 21) & 0x3; | |
| // Immediate goes in bits 20:5 | |
| Contents = (Contents >> 5) & 0xffff; | |
| return Contents << (16 * Shift); | |
| } | |
| } | |
| static uint64_t extractUImmRISCV(uint32_t Contents) { | |
| return SignExtend64<32>(Contents & 0xfffff000); | |
| } | |
| static uint64_t extractIImmRISCV(uint32_t Contents) { | |
| return SignExtend64<12>(Contents >> 20); | |
| } | |
| static uint64_t extractSImmRISCV(uint32_t Contents) { | |
| return SignExtend64<12>(((Contents >> 7) & 0x1f) | ((Contents >> 25) << 5)); | |
| } | |
| static uint64_t extractJImmRISCV(uint32_t Contents) { | |
| return SignExtend64<21>( | |
| (((Contents >> 21) & 0x3ff) << 1) | (((Contents >> 20) & 0x1) << 11) | | |
| (((Contents >> 12) & 0xff) << 12) | (((Contents >> 31) & 0x1) << 20)); | |
| } | |
| static uint64_t extractBImmRISCV(uint32_t Contents) { | |
| return SignExtend64<13>( | |
| (((Contents >> 8) & 0xf) << 1) | (((Contents >> 25) & 0x3f) << 5) | | |
| (((Contents >> 7) & 0x1) << 11) | (((Contents >> 31) & 0x1) << 12)); | |
| } | |
| static uint64_t extractValueRISCV(uint32_t Type, uint64_t Contents, | |
| uint64_t PC) { | |
| switch (Type) { | |
| default: | |
| errs() << object::getELFRelocationTypeName(ELF::EM_RISCV, Type) << '\n'; | |
| llvm_unreachable("unsupported relocation type"); | |
| case ELF::R_RISCV_JAL: | |
| return extractJImmRISCV(Contents); | |
| case ELF::R_RISCV_CALL: | |
| case ELF::R_RISCV_CALL_PLT: | |
| // The psABI "Relocations" chapter's "Procedure Calls" section defines | |
| // R_RISCV_CALL and R_RISCV_CALL_PLT over an AUIPC/JALR pair. Decode both | |
| // instructions so the addend includes the low 12 bits carried by JALR. | |
| return extractUImmRISCV(Contents & 0xffffffff) + | |
| extractIImmRISCV(Contents >> 32); | |
| case ELF::R_RISCV_BRANCH: | |
| return extractBImmRISCV(Contents); | |
| case ELF::R_RISCV_GOT_HI20: | |
| case ELF::R_RISCV_TLS_GOT_HI20: | |
| case ELF::R_RISCV_TLS_GD_HI20: | |
| // We need to know the exact address of the GOT entry so we extract the | |
| // value from both the AUIPC and L[D|W]. We cannot rely on the symbol in the | |
| // relocation for this since it simply refers to the object that is stored | |
| // in the GOT entry, not to the entry itself. | |
| return extractUImmRISCV(Contents & 0xffffffff) + | |
| extractIImmRISCV(Contents >> 32); | |
| case ELF::R_RISCV_PCREL_HI20: | |
| case ELF::R_RISCV_HI20: | |
| return extractUImmRISCV(Contents); | |
| case ELF::R_RISCV_PCREL_LO12_I: | |
| case ELF::R_RISCV_LO12_I: | |
| return extractIImmRISCV(Contents); | |
| case ELF::R_RISCV_PCREL_LO12_S: | |
| case ELF::R_RISCV_LO12_S: | |
| return extractSImmRISCV(Contents); | |
| case ELF::R_RISCV_RVC_JUMP: | |
| return SignExtend64<11>(Contents >> 2); | |
| case ELF::R_RISCV_RVC_BRANCH: | |
| return SignExtend64<8>(((Contents >> 2) & 0x1f) | ((Contents >> 5) & 0xe0)); | |
| case ELF::R_RISCV_ADD32: | |
| case ELF::R_RISCV_SUB32: | |
| case ELF::R_RISCV_32: | |
| case ELF::R_RISCV_64: | |
| return Contents; | |
| } | |
| } | |
| static bool isGOTX86(uint32_t Type) { | |
| switch (Type) { | |
| default: | |
| return false; | |
| case ELF::R_X86_64_GOT32: | |
| case ELF::R_X86_64_GOTPCREL: | |
| case ELF::R_X86_64_GOTTPOFF: | |
| case ELF::R_X86_64_GOTOFF64: | |
| case ELF::R_X86_64_GOTPC32: | |
| case ELF::R_X86_64_GOT64: | |
| case ELF::R_X86_64_GOTPCREL64: | |
| case ELF::R_X86_64_GOTPC64: | |
| case ELF::R_X86_64_GOTPLT64: | |
| case ELF::R_X86_64_GOTPC32_TLSDESC: | |
| case ELF::R_X86_64_GOTPCRELX: | |
| case ELF::R_X86_64_REX_GOTPCRELX: | |
| return true; | |
| } | |
| } | |
| static bool isGOTAArch64(uint32_t Type) { | |
| switch (Type) { | |
| default: | |
| return false; | |
| case ELF::R_AARCH64_ADR_GOT_PAGE: | |
| case ELF::R_AARCH64_LD64_GOT_LO12_NC: | |
| case ELF::R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC: | |
| case ELF::R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21: | |
| case ELF::R_AARCH64_TLSGD_ADR_PAGE21: | |
| case ELF::R_AARCH64_TLSGD_ADD_LO12_NC: | |
| case ELF::R_AARCH64_TLSDESC_ADR_PREL21: | |
| case ELF::R_AARCH64_TLSDESC_ADR_PAGE21: | |
| case ELF::R_AARCH64_TLSDESC_LD64_LO12: | |
| case ELF::R_AARCH64_TLSDESC_ADD_LO12: | |
| return true; | |
| } | |
| } | |
| static bool isGOTRISCV(uint32_t Type) { | |
| switch (Type) { | |
| default: | |
| return false; | |
| case ELF::R_RISCV_GOT_HI20: | |
| case ELF::R_RISCV_TLS_GOT_HI20: | |
| case ELF::R_RISCV_TLS_GD_HI20: | |
| return true; | |
| } | |
| } | |
| static bool isTLSX86(uint32_t Type) { | |
| switch (Type) { | |
| default: | |
| return false; | |
| case ELF::R_X86_64_TPOFF32: | |
| case ELF::R_X86_64_TPOFF64: | |
| case ELF::R_X86_64_GOTTPOFF: | |
| return true; | |
| } | |
| } | |
| static bool isTLSAArch64(uint32_t Type) { | |
| switch (Type) { | |
| default: | |
| return false; | |
| case ELF::R_AARCH64_TLSGD_ADR_PAGE21: | |
| case ELF::R_AARCH64_TLSGD_ADD_LO12_NC: | |
| case ELF::R_AARCH64_TLSDESC_ADR_PREL21: | |
| case ELF::R_AARCH64_TLSDESC_ADR_PAGE21: | |
| case ELF::R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC: | |
| case ELF::R_AARCH64_TLSLE_ADD_TPREL_HI12: | |
| case ELF::R_AARCH64_TLSLE_ADD_TPREL_LO12_NC: | |
| case ELF::R_AARCH64_TLSLE_MOVW_TPREL_G0: | |
| case ELF::R_AARCH64_TLSLE_MOVW_TPREL_G0_NC: | |
| case ELF::R_AARCH64_TLSDESC_LD64_LO12: | |
| case ELF::R_AARCH64_TLSDESC_ADD_LO12: | |
| case ELF::R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21: | |
| return true; | |
| } | |
| } | |
| static bool isTLSRISCV(uint32_t Type) { | |
| switch (Type) { | |
| default: | |
| return false; | |
| case ELF::R_RISCV_TLS_GOT_HI20: | |
| case ELF::R_RISCV_TLS_GD_HI20: | |
| case ELF::R_RISCV_TPREL_HI20: | |
| case ELF::R_RISCV_TPREL_ADD: | |
| case ELF::R_RISCV_TPREL_LO12_I: | |
| case ELF::R_RISCV_TPREL_LO12_S: | |
| case ELFReserved::R_RISCV_TPREL_I: | |
| case ELFReserved::R_RISCV_TPREL_S: | |
| return true; | |
| } | |
| } | |
| static bool isPCRelativeX86(uint32_t Type) { | |
| switch (Type) { | |
| default: | |
| llvm_unreachable("Unknown relocation type"); | |
| case ELF::R_X86_64_64: | |
| case ELF::R_X86_64_32: | |
| case ELF::R_X86_64_32S: | |
| case ELF::R_X86_64_16: | |
| case ELF::R_X86_64_8: | |
| case ELF::R_X86_64_TPOFF32: | |
| return false; | |
| case ELF::R_X86_64_PC8: | |
| case ELF::R_X86_64_PC32: | |
| case ELF::R_X86_64_PC64: | |
| case ELF::R_X86_64_GOTPCREL: | |
| case ELF::R_X86_64_PLT32: | |
| case ELF::R_X86_64_GOTOFF64: | |
| case ELF::R_X86_64_GOTPC32: | |
| case ELF::R_X86_64_GOTPC64: | |
| case ELF::R_X86_64_GOTTPOFF: | |
| case ELF::R_X86_64_GOTPCRELX: | |
| case ELF::R_X86_64_REX_GOTPCRELX: | |
| return true; | |
| } | |
| } | |
| static bool isPCRelativeAArch64(uint32_t Type) { | |
| switch (Type) { | |
| default: | |
| llvm_unreachable("Unknown relocation type"); | |
| case ELF::R_AARCH64_ABS16: | |
| case ELF::R_AARCH64_ABS32: | |
| case ELF::R_AARCH64_ABS64: | |
| case ELF::R_AARCH64_LDST64_ABS_LO12_NC: | |
| case ELF::R_AARCH64_ADD_ABS_LO12_NC: | |
| case ELF::R_AARCH64_LDST128_ABS_LO12_NC: | |
| case ELF::R_AARCH64_LDST32_ABS_LO12_NC: | |
| case ELF::R_AARCH64_LDST16_ABS_LO12_NC: | |
| case ELF::R_AARCH64_LDST8_ABS_LO12_NC: | |
| case ELF::R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC: | |
| case ELF::R_AARCH64_TLSGD_ADD_LO12_NC: | |
| case ELF::R_AARCH64_TLSLE_ADD_TPREL_HI12: | |
| case ELF::R_AARCH64_TLSLE_ADD_TPREL_LO12_NC: | |
| case ELF::R_AARCH64_TLSLE_MOVW_TPREL_G0: | |
| case ELF::R_AARCH64_TLSLE_MOVW_TPREL_G0_NC: | |
| case ELF::R_AARCH64_LD64_GOT_LO12_NC: | |
| case ELF::R_AARCH64_TLSDESC_LD64_LO12: | |
| case ELF::R_AARCH64_TLSDESC_ADD_LO12: | |
| case ELF::R_AARCH64_MOVW_UABS_G0: | |
| case ELF::R_AARCH64_MOVW_UABS_G0_NC: | |
| case ELF::R_AARCH64_MOVW_UABS_G1: | |
| case ELF::R_AARCH64_MOVW_UABS_G1_NC: | |
| case ELF::R_AARCH64_MOVW_UABS_G2: | |
| case ELF::R_AARCH64_MOVW_UABS_G2_NC: | |
| case ELF::R_AARCH64_MOVW_UABS_G3: | |
| return false; | |
| case ELF::R_AARCH64_CALL26: | |
| case ELF::R_AARCH64_JUMP26: | |
| case ELF::R_AARCH64_TSTBR14: | |
| case ELF::R_AARCH64_CONDBR19: | |
| case ELF::R_AARCH64_ADR_PREL_LO21: | |
| case ELF::R_AARCH64_ADR_PREL_PG_HI21: | |
| case ELF::R_AARCH64_ADR_PREL_PG_HI21_NC: | |
| case ELF::R_AARCH64_ADR_GOT_PAGE: | |
| case ELF::R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21: | |
| case ELF::R_AARCH64_TLSGD_ADR_PAGE21: | |
| case ELF::R_AARCH64_TLSDESC_ADR_PREL21: | |
| case ELF::R_AARCH64_TLSDESC_ADR_PAGE21: | |
| case ELF::R_AARCH64_PREL16: | |
| case ELF::R_AARCH64_PREL32: | |
| case ELF::R_AARCH64_PREL64: | |
| case ELF::R_AARCH64_PLT32: | |
| return true; | |
| } | |
| } | |
| static bool isPCRelativeRISCV(uint32_t Type) { | |
| switch (Type) { | |
| default: | |
| llvm_unreachable("Unknown relocation type"); | |
| case ELF::R_RISCV_ADD32: | |
| case ELF::R_RISCV_SUB32: | |
| case ELF::R_RISCV_HI20: | |
| case ELF::R_RISCV_LO12_I: | |
| case ELF::R_RISCV_LO12_S: | |
| case ELF::R_RISCV_32: | |
| case ELF::R_RISCV_64: | |
| return false; | |
| case ELF::R_RISCV_JAL: | |
| case ELF::R_RISCV_CALL: | |
| case ELF::R_RISCV_CALL_PLT: | |
| case ELF::R_RISCV_BRANCH: | |
| case ELF::R_RISCV_GOT_HI20: | |
| case ELF::R_RISCV_PCREL_HI20: | |
| case ELF::R_RISCV_PCREL_LO12_I: | |
| case ELF::R_RISCV_PCREL_LO12_S: | |
| case ELF::R_RISCV_RVC_JUMP: | |
| case ELF::R_RISCV_RVC_BRANCH: | |
| case ELF::R_RISCV_32_PCREL: | |
| case ELF::R_RISCV_TLS_GOT_HI20: | |
| case ELF::R_RISCV_TLS_GD_HI20: | |
| return true; | |
| } | |
| } | |
| bool Relocation::isSupported(uint32_t Type) { | |
| switch (Arch) { | |
| default: | |
| return false; | |
| case Triple::aarch64: | |
| return isSupportedAArch64(Type); | |
| case Triple::riscv64: | |
| case Triple::riscv32: | |
| return isSupportedRISCV(Type); | |
| case Triple::x86_64: | |
| return isSupportedX86(Type); | |
| } | |
| } | |
| size_t Relocation::getSizeForType(uint32_t Type) { | |
| switch (Arch) { | |
| default: | |
| llvm_unreachable("Unsupported architecture"); | |
| case Triple::aarch64: | |
| return getSizeForTypeAArch64(Type); | |
| case Triple::riscv64: | |
| case Triple::riscv32: | |
| return getSizeForTypeRISCV(Type); | |
| case Triple::x86_64: | |
| return getSizeForTypeX86(Type); | |
| } | |
| } | |
| bool Relocation::skipRelocationType(uint32_t Type) { | |
| switch (Arch) { | |
| default: | |
| llvm_unreachable("Unsupported architecture"); | |
| case Triple::aarch64: | |
| return skipRelocationTypeAArch64(Type); | |
| case Triple::riscv64: | |
| case Triple::riscv32: | |
| return skipRelocationTypeRISCV(Type); | |
| case Triple::x86_64: | |
| return skipRelocationTypeX86(Type); | |
| } | |
| } | |
| uint64_t Relocation::encodeValue(uint32_t Type, uint64_t Value, uint64_t PC) { | |
| switch (Arch) { | |
| default: | |
| llvm_unreachable("Unsupported architecture"); | |
| case Triple::aarch64: | |
| return encodeValueAArch64(Type, Value, PC); | |
| case Triple::riscv64: | |
| case Triple::riscv32: | |
| return encodeValueRISCV(Type, Value, PC); | |
| case Triple::x86_64: | |
| return encodeValueX86(Type, Value, PC); | |
| } | |
| } | |
| bool Relocation::canEncodeValue(uint32_t Type, uint64_t Value, uint64_t PC) { | |
| switch (Arch) { | |
| default: | |
| llvm_unreachable("Unsupported architecture"); | |
| case Triple::aarch64: | |
| return canEncodeValueAArch64(Type, Value, PC); | |
| case Triple::riscv64: | |
| case Triple::riscv32: | |
| return canEncodeValueRISCV(Type, Value, PC); | |
| case Triple::x86_64: | |
| return true; | |
| } | |
| } | |
| uint64_t Relocation::extractValue(uint32_t Type, uint64_t Contents, | |
| uint64_t PC) { | |
| switch (Arch) { | |
| default: | |
| llvm_unreachable("Unsupported architecture"); | |
| case Triple::aarch64: | |
| return extractValueAArch64(Type, Contents, PC); | |
| case Triple::riscv64: | |
| case Triple::riscv32: | |
| return extractValueRISCV(Type, Contents, PC); | |
| case Triple::x86_64: | |
| return extractValueX86(Type, Contents, PC); | |
| } | |
| } | |
| bool Relocation::isGOT(uint32_t Type) { | |
| switch (Arch) { | |
| default: | |
| llvm_unreachable("Unsupported architecture"); | |
| case Triple::aarch64: | |
| return isGOTAArch64(Type); | |
| case Triple::riscv64: | |
| case Triple::riscv32: | |
| return isGOTRISCV(Type); | |
| case Triple::x86_64: | |
| return isGOTX86(Type); | |
| } | |
| } | |
| bool Relocation::isX86GOTPCRELX(uint32_t Type) { | |
| if (Arch != Triple::x86_64) | |
| return false; | |
| return Type == ELF::R_X86_64_GOTPCRELX || Type == ELF::R_X86_64_REX_GOTPCRELX; | |
| } | |
| bool Relocation::isX86GOTPC64(uint32_t Type) { | |
| if (Arch != Triple::x86_64) | |
| return false; | |
| return Type == ELF::R_X86_64_GOTPC64; | |
| } | |
| bool Relocation::isNone(uint32_t Type) { return Type == getNone(); } | |
| bool Relocation::isRelative(uint32_t Type) { | |
| switch (Arch) { | |
| default: | |
| llvm_unreachable("Unsupported architecture"); | |
| case Triple::aarch64: | |
| return Type == ELF::R_AARCH64_RELATIVE; | |
| case Triple::riscv64: | |
| case Triple::riscv32: | |
| return Type == ELF::R_RISCV_RELATIVE; | |
| case Triple::x86_64: | |
| return Type == ELF::R_X86_64_RELATIVE; | |
| } | |
| } | |
| bool Relocation::isIRelative(uint32_t Type) { | |
| switch (Arch) { | |
| default: | |
| llvm_unreachable("Unsupported architecture"); | |
| case Triple::aarch64: | |
| return Type == ELF::R_AARCH64_IRELATIVE; | |
| case Triple::riscv64: | |
| return Type == ELF::R_RISCV_IRELATIVE; | |
| case Triple::riscv32: | |
| llvm_unreachable("not implemented"); | |
| case Triple::x86_64: | |
| return Type == ELF::R_X86_64_IRELATIVE; | |
| } | |
| } | |
| bool Relocation::isTLS(uint32_t Type) { | |
| switch (Arch) { | |
| default: | |
| llvm_unreachable("Unsupported architecture"); | |
| case Triple::aarch64: | |
| return isTLSAArch64(Type); | |
| case Triple::riscv64: | |
| case Triple::riscv32: | |
| return isTLSRISCV(Type); | |
| case Triple::x86_64: | |
| return isTLSX86(Type); | |
| } | |
| } | |
| bool Relocation::isInstructionReference(uint32_t Type) { | |
| if (Arch != Triple::riscv64 && Arch != Triple::riscv32) | |
| return false; | |
| switch (Type) { | |
| default: | |
| return false; | |
| case ELF::R_RISCV_PCREL_LO12_I: | |
| case ELF::R_RISCV_PCREL_LO12_S: | |
| return true; | |
| } | |
| } | |
| uint32_t Relocation::getNone() { | |
| switch (Arch) { | |
| default: | |
| llvm_unreachable("Unsupported architecture"); | |
| case Triple::aarch64: | |
| return ELF::R_AARCH64_NONE; | |
| case Triple::riscv64: | |
| case Triple::riscv32: | |
| return ELF::R_RISCV_NONE; | |
| case Triple::x86_64: | |
| return ELF::R_X86_64_NONE; | |
| } | |
| } | |
| uint32_t Relocation::getPC32() { | |
| switch (Arch) { | |
| default: | |
| llvm_unreachable("Unsupported architecture"); | |
| case Triple::aarch64: | |
| return ELF::R_AARCH64_PREL32; | |
| case Triple::riscv64: | |
| case Triple::riscv32: | |
| return ELF::R_RISCV_32_PCREL; | |
| case Triple::x86_64: | |
| return ELF::R_X86_64_PC32; | |
| } | |
| } | |
| uint32_t Relocation::getPC64() { | |
| switch (Arch) { | |
| default: | |
| llvm_unreachable("Unsupported architecture"); | |
| case Triple::aarch64: | |
| return ELF::R_AARCH64_PREL64; | |
| case Triple::riscv64: | |
| case Triple::riscv32: | |
| llvm_unreachable("not implemented"); | |
| case Triple::x86_64: | |
| return ELF::R_X86_64_PC64; | |
| } | |
| } | |
| uint32_t Relocation::getType(const object::RelocationRef &Rel) { | |
| uint64_t RelType = Rel.getType(); | |
| assert(isUInt<32>(RelType) && "BOLT relocation types are 32 bits"); | |
| return static_cast<uint32_t>(RelType); | |
| } | |
| bool Relocation::isPCRelative(uint32_t Type) { | |
| switch (Arch) { | |
| default: | |
| llvm_unreachable("Unsupported architecture"); | |
| case Triple::aarch64: | |
| return isPCRelativeAArch64(Type); | |
| case Triple::riscv64: | |
| case Triple::riscv32: | |
| return isPCRelativeRISCV(Type); | |
| case Triple::x86_64: | |
| return isPCRelativeX86(Type); | |
| } | |
| } | |
| uint32_t Relocation::getAbs64() { | |
| switch (Arch) { | |
| default: | |
| llvm_unreachable("Unsupported architecture"); | |
| case Triple::aarch64: | |
| return ELF::R_AARCH64_ABS64; | |
| case Triple::riscv64: | |
| case Triple::riscv32: | |
| return ELF::R_RISCV_64; | |
| case Triple::x86_64: | |
| return ELF::R_X86_64_64; | |
| } | |
| } | |
| uint32_t Relocation::getRelative() { | |
| switch (Arch) { | |
| default: | |
| llvm_unreachable("Unsupported architecture"); | |
| case Triple::aarch64: | |
| return ELF::R_AARCH64_RELATIVE; | |
| case Triple::riscv64: | |
| return ELF::R_RISCV_RELATIVE; | |
| case Triple::riscv32: | |
| llvm_unreachable("not implemented"); | |
| case Triple::x86_64: | |
| return ELF::R_X86_64_RELATIVE; | |
| } | |
| } | |
| size_t Relocation::emit(MCStreamer *Streamer) const { | |
| const size_t Size = getSizeForType(Type); | |
| const auto *Value = createExpr(Streamer); | |
| Streamer->emitValue(Value, Size); | |
| return Size; | |
| } | |
| const MCExpr *Relocation::createExpr(MCStreamer *Streamer) const { | |
| MCContext &Ctx = Streamer->getContext(); | |
| const MCExpr *Value = nullptr; | |
| if (Symbol && Addend) { | |
| Value = MCBinaryExpr::createAdd(MCSymbolRefExpr::create(Symbol, Ctx), | |
| MCConstantExpr::create(Addend, Ctx), Ctx); | |
| } else if (Symbol) { | |
| Value = MCSymbolRefExpr::create(Symbol, Ctx); | |
| } else { | |
| Value = MCConstantExpr::create(Addend, Ctx); | |
| } | |
| if (isPCRelative(Type)) { | |
| MCSymbol *TempLabel = Ctx.createNamedTempSymbol(); | |
| Streamer->emitLabel(TempLabel); | |
| Value = MCBinaryExpr::createSub( | |
| Value, MCSymbolRefExpr::create(TempLabel, Ctx), Ctx); | |
| } | |
| return Value; | |
| } | |
| const MCExpr *Relocation::createExpr(MCStreamer *Streamer, | |
| const MCExpr *RetainedValue) const { | |
| const auto *Value = createExpr(Streamer); | |
| if (RetainedValue) { | |
| Value = MCBinaryExpr::create(getComposeOpcodeFor(Type), RetainedValue, | |
| Value, Streamer->getContext()); | |
| } | |
| return Value; | |
| } | |
| MCBinaryExpr::Opcode Relocation::getComposeOpcodeFor(uint32_t Type) { | |
| assert((Arch == Triple::riscv32 || Arch == Triple::riscv64) && | |
| "only implemented for RISC-V"); | |
| switch (Type) { | |
| default: | |
| llvm_unreachable("not implemented"); | |
| case ELF::R_RISCV_ADD32: | |
| return MCBinaryExpr::Add; | |
| case ELF::R_RISCV_SUB32: | |
| return MCBinaryExpr::Sub; | |
| } | |
| } | |
| void Relocation::print(raw_ostream &OS) const { | |
| switch (Arch) { | |
| default: | |
| OS << "RType:" << Twine::utohexstr(Type); | |
| break; | |
| case Triple::aarch64: | |
| OS << object::getELFRelocationTypeName(ELF::EM_AARCH64, Type); | |
| break; | |
| case Triple::riscv64: | |
| case Triple::riscv32: | |
| OS << object::getELFRelocationTypeName(ELF::EM_RISCV, Type); | |
| break; | |
| case Triple::x86_64: | |
| OS << object::getELFRelocationTypeName(ELF::EM_X86_64, Type); | |
| break; | |
| } | |
| OS << ", 0x" << Twine::utohexstr(Offset); | |
| if (Symbol) { | |
| OS << ", " << Symbol->getName(); | |
| } | |
| if (int64_t(Addend) < 0) | |
| OS << ", -0x" << Twine::utohexstr(-int64_t(Addend)); | |
| else | |
| OS << ", 0x" << Twine::utohexstr(Addend); | |
| OS << ", 0x" << Twine::utohexstr(Value); | |
| } |