1 //===-- CSKYELFObjectWriter.cpp - CSKY ELF Writer -------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "CSKYFixupKinds.h"
10 #include "CSKYMCExpr.h"
11 #include "CSKYMCTargetDesc.h"
12 #include "llvm/MC/MCContext.h"
13 #include "llvm/MC/MCELFObjectWriter.h"
14 #include "llvm/MC/MCObjectWriter.h"
15 
16 #define DEBUG_TYPE "csky-elf-object-writer"
17 
18 using namespace llvm;
19 
20 namespace {
21 
22 class CSKYELFObjectWriter : public MCELFObjectTargetWriter {
23 public:
24   CSKYELFObjectWriter(uint8_t OSABI = 0)
25       : MCELFObjectTargetWriter(false, OSABI, ELF::EM_CSKY, true){};
26   ~CSKYELFObjectWriter() {}
27 
28   unsigned getRelocType(MCContext &Ctx, const MCValue &Target,
29                         const MCFixup &Fixup, bool IsPCRel) const override;
30 };
31 
32 } // namespace
33 
34 unsigned CSKYELFObjectWriter::getRelocType(MCContext &Ctx,
35                                            const MCValue &Target,
36                                            const MCFixup &Fixup,
37                                            bool IsPCRel) const {
38   const MCExpr *Expr = Fixup.getValue();
39   // Determine the type of the relocation
40   unsigned Kind = Fixup.getTargetKind();
41   MCSymbolRefExpr::VariantKind Modifier = Target.getAccessVariant();
42 
43   if (IsPCRel) {
44     switch (Kind) {
45     default:
46       LLVM_DEBUG(dbgs() << "Unknown Kind1  = " << Kind);
47       Ctx.reportError(Fixup.getLoc(), "Unsupported relocation type");
48       return ELF::R_CKCORE_NONE;
49     case FK_Data_4:
50     case FK_PCRel_4:
51       return ELF::R_CKCORE_PCREL32;
52     case CSKY::fixup_csky_pcrel_uimm16_scale4:
53       return ELF::R_CKCORE_PCREL_IMM16_4;
54     case CSKY::fixup_csky_pcrel_uimm8_scale4:
55       return ELF::R_CKCORE_PCREL_IMM8_4;
56     case CSKY::fixup_csky_pcrel_imm26_scale2:
57       return ELF::R_CKCORE_PCREL_IMM26_2;
58     case CSKY::fixup_csky_pcrel_imm18_scale2:
59       return ELF::R_CKCORE_PCREL_IMM18_2;
60     case CSKY::fixup_csky_pcrel_imm16_scale2:
61       return ELF::R_CKCORE_PCREL_IMM16_2;
62     case CSKY::fixup_csky_pcrel_imm10_scale2:
63       return ELF::R_CKCORE_PCREL_IMM10_2;
64     case CSKY::fixup_csky_pcrel_uimm7_scale4:
65       return ELF::R_CKCORE_PCREL_IMM7_4;
66     }
67   }
68 
69   switch (Kind) {
70   default:
71     LLVM_DEBUG(dbgs() << "Unknown Kind2  = " << Kind);
72     Ctx.reportError(Fixup.getLoc(), "Unsupported relocation type");
73     return ELF::R_CKCORE_NONE;
74   case FK_Data_1:
75     Ctx.reportError(Fixup.getLoc(), "1-byte data relocations not supported");
76     return ELF::R_CKCORE_NONE;
77   case FK_Data_2:
78     Ctx.reportError(Fixup.getLoc(), "2-byte data relocations not supported");
79     return ELF::R_CKCORE_NONE;
80   case FK_Data_4:
81     if (Expr->getKind() == MCExpr::Target) {
82       auto TK = cast<CSKYMCExpr>(Expr)->getKind();
83       if (TK == CSKYMCExpr::VK_CSKY_ADDR)
84         return ELF::R_CKCORE_ADDR32;
85       if (TK == CSKYMCExpr::VK_CSKY_GOT)
86         return ELF::R_CKCORE_GOT32;
87       if (TK == CSKYMCExpr::VK_CSKY_GOTOFF)
88         return ELF::R_CKCORE_GOTOFF;
89       if (TK == CSKYMCExpr::VK_CSKY_PLT)
90         return ELF::R_CKCORE_PLT32;
91       if (TK == CSKYMCExpr::VK_CSKY_TLSIE)
92         return ELF::R_CKCORE_TLS_IE32;
93       if (TK == CSKYMCExpr::VK_CSKY_TLSLE)
94         return ELF::R_CKCORE_TLS_LE32;
95       if (TK == CSKYMCExpr::VK_CSKY_TLSGD)
96         return ELF::R_CKCORE_TLS_GD32;
97       if (TK == CSKYMCExpr::VK_CSKY_TLSLDM)
98         return ELF::R_CKCORE_TLS_LDM32;
99       if (TK == CSKYMCExpr::VK_CSKY_TLSLDO)
100         return ELF::R_CKCORE_TLS_LDO32;
101       if (TK == CSKYMCExpr::VK_CSKY_GOTPC)
102         return ELF::R_CKCORE_GOTPC;
103       if (TK == CSKYMCExpr::VK_CSKY_None)
104         return ELF::R_CKCORE_ADDR32;
105 
106       LLVM_DEBUG(dbgs() << "Unknown FK_Data_4 TK  = " << TK);
107       Ctx.reportError(Fixup.getLoc(), "unknown target FK_Data_4");
108     } else {
109       switch (Modifier) {
110       default:
111         Ctx.reportError(Fixup.getLoc(),
112                         "invalid fixup for 4-byte data relocation");
113         return ELF::R_CKCORE_NONE;
114       case MCSymbolRefExpr::VK_GOT:
115         return ELF::R_CKCORE_GOT32;
116       case MCSymbolRefExpr::VK_GOTOFF:
117         return ELF::R_CKCORE_GOTOFF;
118       case MCSymbolRefExpr::VK_PLT:
119         return ELF::R_CKCORE_PLT32;
120       case MCSymbolRefExpr::VK_None:
121         return ELF::R_CKCORE_ADDR32;
122       }
123     }
124     return ELF::R_CKCORE_NONE;
125   case FK_Data_8:
126     Ctx.reportError(Fixup.getLoc(), "8-byte data relocations not supported");
127     return ELF::R_CKCORE_NONE;
128   case CSKY::fixup_csky_addr32:
129     return ELF::R_CKCORE_ADDR32;
130   case CSKY::fixup_csky_addr_hi16:
131     return ELF::R_CKCORE_ADDR_HI16;
132   case CSKY::fixup_csky_addr_lo16:
133     return ELF::R_CKCORE_ADDR_LO16;
134   case CSKY::fixup_csky_doffset_imm18:
135     return ELF::R_CKCORE_DOFFSET_IMM18;
136   case CSKY::fixup_csky_doffset_imm18_scale2:
137     return ELF::R_CKCORE_DOFFSET_IMM18_2;
138   case CSKY::fixup_csky_doffset_imm18_scale4:
139     return ELF::R_CKCORE_DOFFSET_IMM18_4;
140   case CSKY::fixup_csky_got_imm18_scale4:
141     return ELF::R_CKCORE_GOT_IMM18_4;
142   case CSKY::fixup_csky_plt_imm18_scale4:
143     return ELF::R_CKCORE_PLT_IMM18_4;
144   }
145 }
146 
147 std::unique_ptr<MCObjectTargetWriter> llvm::createCSKYELFObjectWriter() {
148   return std::make_unique<CSKYELFObjectWriter>();
149 }
150