mirror of
https://github.com/rui314/mold.git
synced 2026-11-08 17:48:41 -10:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
57f5c77174 |
No files matched your search
+2
-1
@@ -311,7 +311,7 @@ include_directories(${CMAKE_CURRENT_BINARY_DIR})
|
||||
# on a multicore machine.
|
||||
list(APPEND MOLD_ELF_TARGETS
|
||||
X86_64 I386 ARM64LE ARM64BE ARM32 RV32LE RV32BE RV64LE RV64BE PPC32
|
||||
PPC64V1 PPC64V2 S390X SPARC64 M68K SH4LE SH4BE LOONGARCH32 LOONGARCH64)
|
||||
PPC64V1 PPC64V2 S390X SPARC64 M68K SH4LE SH4BE LOONGARCH32 LOONGARCH64 ARC)
|
||||
|
||||
list(APPEND MOLD_ELF_TEMPLATE_FILES
|
||||
src/arch-arm64.cc
|
||||
@@ -385,6 +385,7 @@ target_sources(mold PRIVATE
|
||||
lib/perf.cc
|
||||
lib/random.cc
|
||||
lib/tar.cc
|
||||
src/arch-arc.cc
|
||||
src/arch-arm32.cc
|
||||
src/arch-i386.cc
|
||||
src/arch-m68k.cc
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
#!/bin/bash -x
|
||||
set -e
|
||||
apt-get install -y git bzip2 ninja-build pkg-config libglib2.0-dev python3-distutils-extra libpixman-1-dev
|
||||
|
||||
cd /
|
||||
git clone --depth=1 https://github.com/foss-for-synopsys-dwc-arc-processors/qemu.git
|
||||
mkdir /qemu/build
|
||||
cd /qemu/build
|
||||
../configure --static --extra-cflags=-Wno-error
|
||||
ninja
|
||||
ln -s /qemu/build/qemu-arc /qemu/build/qemu-arc64 /usr/local/bin
|
||||
|
||||
|
||||
apt-get install -y libgmp-dev libmpfr-dev texinfo bison yacc flex
|
||||
cd /
|
||||
git clone --depth=1 https://github.com/foss-for-synopsys-dwc-arc-processors/binutils-gdb.git
|
||||
cd /binutils-gdb
|
||||
mkdir build
|
||||
cd build
|
||||
../configure --target=arc-linux
|
||||
make -j$(nproc)
|
||||
|
||||
|
||||
apt-get install -y mold
|
||||
mkdir /build
|
||||
cd /build
|
||||
cmake -GNinja -DCMAKE_BUILD_TYPE=Debug -DMOLD_USE_MOLD=1 /mold
|
||||
ninja
|
||||
TRIPLE=arc-linux-gnu bash -x /mold/test/hello-dynamic.sh
|
||||
@@ -11,7 +11,7 @@ set -x
|
||||
|
||||
case "$ID" in
|
||||
ubuntu | pop | linuxmint | debian | raspbian)
|
||||
apt-get install -y qemu-user {gcc,g++}-{i686,aarch64,riscv64,powerpc,powerpc64,powerpc64le,s390x,sparc64,m68k,sh4}-linux-gnu {gcc,g++}-arm-linux-gnueabihf
|
||||
apt-get install -y qemu-user {gcc,g++}-{i686,aarch64,riscv64,powerpc,powerpc64,powerpc64le,s390x,sparc64,m68k,sh4,arc}-linux-gnu {gcc,g++}-arm-linux-gnueabihf
|
||||
;;
|
||||
*)
|
||||
echo "Error: don't know anything about build dependencies on $ID-$VERSION_ID"
|
||||
|
||||
+285
@@ -0,0 +1,285 @@
|
||||
// r31 is blink. r30 is I believe a scratch register.
|
||||
//
|
||||
// Programs might use one of several branch, jump, and link instructions
|
||||
// to control execution flow through direct and indirect function calls
|
||||
// and branching. For function calling, the conditional branch-and-link
|
||||
// instruction has a maximum branch range of ±1 MiB, and the target
|
||||
// address is 32-bit-aligned. The unconditional branch-and-link format has
|
||||
// a maximum branch range of ±16 MiB.
|
||||
//
|
||||
// https://github.com/foss-for-synopsys-dwc-arc-processors/arc-ABI-manual/blob/master/ARCv2_ABI.pdf
|
||||
|
||||
#include "mold.h"
|
||||
|
||||
namespace mold {
|
||||
|
||||
using E = ARC;
|
||||
|
||||
// An integer-like class for the mixed-endian encoding
|
||||
class M32 {
|
||||
public:
|
||||
operator u32() const {
|
||||
return (buf[1] << 24) | (buf[0] << 16) | (buf[3] << 8) | buf[2];
|
||||
}
|
||||
|
||||
M32 &operator=(u32 x) {
|
||||
buf[0] = x >> 16;
|
||||
buf[1] = x >> 24;
|
||||
buf[2] = x;
|
||||
buf[3] = x >> 8;
|
||||
return *this;
|
||||
}
|
||||
|
||||
M32 &operator&=(u32 x) { return *this = *this & x; }
|
||||
M32 &operator|=(u32 x) { return *this = *this | x; }
|
||||
u8 buf[4];
|
||||
};
|
||||
|
||||
static void write_disp7u(u8 *loc, u32 val) {
|
||||
*(ul16 *)loc |= (bits(val, 6, 3) << 4) | bits(val, 2, 0);
|
||||
}
|
||||
|
||||
static void write_disp9(u8 *loc, u32 val) {
|
||||
*(M32 *)loc |= bits(val, 8, 0);
|
||||
}
|
||||
|
||||
static void write_disp9ls(u8 *loc, u32 val) {
|
||||
*(M32 *)loc |= (bits(val, 7, 0) << 16) | (bit(val, 8) << 15);
|
||||
}
|
||||
|
||||
static void write_disp9s(u8 *loc, u32 val) {
|
||||
*(ul16 *)loc |= bits(val, 8, 0);
|
||||
}
|
||||
|
||||
static void write_disp10u(u8 *loc, u32 val) {
|
||||
*(ul16 *)loc |= bits(val, 9, 0);
|
||||
}
|
||||
|
||||
static void write_disp13s(u8 *loc, u32 val) {
|
||||
*(ul16 *)loc |= bits(val, 12, 0);
|
||||
}
|
||||
|
||||
static void write_disp21h(u8 *loc, u32 val) {
|
||||
*(M32 *)loc |= (bits(val, 10, 1) << 17) | (bits(val, 20, 11) << 6);
|
||||
}
|
||||
|
||||
static void write_disp21w(u8 *loc, u32 val) {
|
||||
*(M32 *)loc |= (bits(val, 10, 2) << 18) | (bits(val, 20, 11) << 6);
|
||||
}
|
||||
|
||||
static void write_disp25h(u8 *loc, u32 val) {
|
||||
*(M32 *)loc |= (bits(val, 10, 1) << 17) | (bits(val, 20, 11) << 6) |
|
||||
bits(val, 24, 21);
|
||||
}
|
||||
|
||||
static void write_disp25w(u8 *loc, u32 val) {
|
||||
*(M32 *)loc |= (bits(val, 10, 2) << 18) | (bits(val, 20, 11) << 6) |
|
||||
bits(val, 24, 21);
|
||||
}
|
||||
|
||||
static void write_disps9(u8 *loc, u32 val) {
|
||||
*(ul16 *)loc |= bits(val, 10, 2);
|
||||
}
|
||||
|
||||
static void write_disps12(u8 *loc, u32 val) {
|
||||
*(M32 *)loc |= (bits(val, 5, 0) << 6) | bits(val, 11, 6);
|
||||
}
|
||||
|
||||
template <>
|
||||
void write_plt_header(Context<E> &ctx, u8 *buf) {
|
||||
static const ul16 insn[] = {
|
||||
0x2730, 0x7f8b, 0, 0, // ld r11, [pcl,0]
|
||||
0x2730, 0x7f8a, 0, 0, // ld r10, [pcl,0]
|
||||
0x2020, 0x0280, // j [r10]
|
||||
0, 0, // (address of GOTPLT)
|
||||
};
|
||||
|
||||
memcpy(buf, insn, sizeof(insn));
|
||||
*(M32 *)(buf + 4) = ctx.gotplt->shdr.sh_addr - ctx.plt->shdr.sh_addr + 4;
|
||||
*(M32 *)(buf + 12) = ctx.gotplt->shdr.sh_addr - ctx.plt->shdr.sh_addr;
|
||||
*(M32 *)(buf + 20) = ctx.gotplt->shdr.sh_addr;
|
||||
}
|
||||
|
||||
template <>
|
||||
void write_plt_entry(Context<E> &ctx, u8 *buf, Symbol<E> &sym) {
|
||||
static const ul16 insn[] = {
|
||||
0x2730, 0x7f8c, 0, 0, // ld r12, [pcl,0]
|
||||
0x2021, 0x0300, // j.d [r12]
|
||||
0x240a, 0x1fc0, // mov r12,pcl
|
||||
};
|
||||
|
||||
memcpy(buf, insn, sizeof(insn));
|
||||
*(M32 *)(buf + 4) = sym.get_gotplt_addr(ctx) - sym.get_plt_addr(ctx);
|
||||
}
|
||||
|
||||
template <>
|
||||
void write_pltgot_entry(Context<E> &ctx, u8 *buf, Symbol<E> &sym) {
|
||||
static const ul16 insn[] = {
|
||||
0x2730, 0x7f8c, 0, 0, // ld r12, [pcl,0]
|
||||
0x2021, 0x0300, // j.d [r12]
|
||||
0x240a, 0x1fc0, // mov r12,pcl
|
||||
};
|
||||
|
||||
memcpy(buf, insn, sizeof(insn));
|
||||
*(M32 *)(buf + 4) = sym.get_got_pltgot_addr(ctx) - sym.get_plt_addr(ctx);
|
||||
}
|
||||
|
||||
template <>
|
||||
void EhFrameSection<E>::apply_eh_reloc(Context<E> &ctx, const ElfRel<E> &rel,
|
||||
u64 offset, u64 val) {
|
||||
u8 *loc = ctx.buf + this->shdr.sh_offset + offset;
|
||||
|
||||
switch (rel.r_type) {
|
||||
case R_NONE:
|
||||
break;
|
||||
case R_ARC_32:
|
||||
*(ul32 *)loc = val;
|
||||
break;
|
||||
case R_ARC_32_PCREL:
|
||||
*(ul32 *)loc = val - this->shdr.sh_addr - offset;
|
||||
break;
|
||||
default:
|
||||
Fatal(ctx) << "unsupported relocation in .eh_frame: " << rel;
|
||||
}
|
||||
}
|
||||
|
||||
template <>
|
||||
void InputSection<E>::apply_reloc_alloc(Context<E> &ctx, u8 *base) {
|
||||
std::span<const ElfRel<E>> rels = get_rels(ctx);
|
||||
|
||||
for (i64 i = 0; i < rels.size(); i++) {
|
||||
const ElfRel<E> &rel = rels[i];
|
||||
if (rel.r_type == R_NONE)
|
||||
continue;
|
||||
|
||||
Symbol<E> &sym = *file.symbols[rel.r_sym];
|
||||
u8 *loc = base + rel.r_offset;
|
||||
|
||||
u64 S = sym.get_addr(ctx);
|
||||
u64 A = rel.r_addend;
|
||||
u64 P = get_addr() + rel.r_offset;
|
||||
u64 G = sym.get_got_idx(ctx) * sizeof(Word<E>);
|
||||
u64 GOT = ctx.got->shdr.sh_addr;
|
||||
|
||||
switch (rel.r_type) {
|
||||
case R_ARC_32:
|
||||
*(ul32 *)loc = S + A;
|
||||
break;
|
||||
case R_ARC_32_ME:
|
||||
*(M32 *)loc = S + A;
|
||||
break;
|
||||
case R_ARC_S25H_PCREL:
|
||||
case R_ARC_S25H_PCREL_PLT:
|
||||
write_disp25h(loc, align_to(S + A - P, 2));
|
||||
break;
|
||||
case R_ARC_S25W_PCREL:
|
||||
case R_ARC_S25W_PCREL_PLT:
|
||||
write_disp25w(loc, align_to(S + A - P, 4));
|
||||
break;
|
||||
case R_ARC_PC32:
|
||||
*(M32 *)loc = S + A - P;
|
||||
break;
|
||||
case R_ARC_32_PCREL:
|
||||
*(ul32 *)loc = S + A - P;
|
||||
break;
|
||||
case R_ARC_GOTPC32:
|
||||
*(M32 *)loc = GOT + G + A - P;
|
||||
break;
|
||||
case R_ARC_TLS_LE_32:
|
||||
*(M32 *)loc = S + A - ctx.tp_addr;
|
||||
break;
|
||||
case R_ARC_TLS_IE_GOT:
|
||||
*(M32 *)loc = sym.get_gottp_addr(ctx) + A - P;
|
||||
break;
|
||||
default:
|
||||
unreachable();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <>
|
||||
void InputSection<E>::apply_reloc_nonalloc(Context<E> &ctx, u8 *base) {
|
||||
std::span<const ElfRel<E>> rels = get_rels(ctx);
|
||||
|
||||
for (i64 i = 0; i < rels.size(); i++) {
|
||||
const ElfRel<E> &rel = rels[i];
|
||||
if (rel.r_type == R_NONE || record_undef_error(ctx, rel))
|
||||
continue;
|
||||
|
||||
Symbol<E> &sym = *file.symbols[rel.r_sym];
|
||||
u8 *loc = base + rel.r_offset;
|
||||
|
||||
SectionFragment<E> *frag;
|
||||
i64 frag_addend;
|
||||
std::tie(frag, frag_addend) = get_fragment(ctx, rel);
|
||||
|
||||
u64 S = frag ? frag->get_addr(ctx) : sym.get_addr(ctx);
|
||||
u64 A = frag ? frag_addend : (i64)rel.r_addend;
|
||||
|
||||
switch (rel.r_type) {
|
||||
case R_ARC_32:
|
||||
if (std::optional<u64> val = get_tombstone(sym, frag))
|
||||
*(ul32 *)loc = *val;
|
||||
else
|
||||
*(ul32 *)loc = S + A;
|
||||
break;
|
||||
default:
|
||||
Fatal(ctx) << *this << ": invalid relocation for non-allocated sections: "
|
||||
<< rel;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <>
|
||||
void InputSection<E>::scan_relocations(Context<E> &ctx) {
|
||||
assert(shdr().sh_flags & SHF_ALLOC);
|
||||
std::span<const ElfRel<E>> rels = get_rels(ctx);
|
||||
|
||||
for (i64 i = 0; i < rels.size(); i++) {
|
||||
const ElfRel<E> &rel = rels[i];
|
||||
if (rel.r_type == R_NONE || record_undef_error(ctx, rel))
|
||||
continue;
|
||||
|
||||
Symbol<E> &sym = *file.symbols[rel.r_sym];
|
||||
|
||||
if (sym.is_ifunc())
|
||||
Error(ctx) << sym << ": GNU ifunc symbol is not supported on m68k";
|
||||
|
||||
switch (rel.r_type) {
|
||||
case R_ARC_32:
|
||||
break;
|
||||
case R_ARC_32_ME:
|
||||
scan_absrel(ctx, sym, rel);
|
||||
break;
|
||||
case R_ARC_S25H_PCREL:
|
||||
case R_ARC_S25W_PCREL:
|
||||
case R_ARC_32_PCREL:
|
||||
case R_ARC_PC32:
|
||||
scan_pcrel(ctx, sym, rel);
|
||||
break;
|
||||
case R_ARC_S25H_PCREL_PLT:
|
||||
case R_ARC_S25W_PCREL_PLT:
|
||||
if (sym.is_imported)
|
||||
sym.flags |= NEEDS_PLT;
|
||||
break;
|
||||
case R_ARC_GOTPC32:
|
||||
sym.flags |= NEEDS_GOT;
|
||||
break;
|
||||
case R_ARC_TLS_LE_32:
|
||||
check_tlsle(ctx, sym, rel);
|
||||
break;
|
||||
case R_ARC_TLS_IE_GOT:
|
||||
sym.flags |= NEEDS_GOTTP;
|
||||
break;
|
||||
default:
|
||||
Error(ctx) << *this << ": unknown relocation: " << rel;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <>
|
||||
u64 get_eflags(Context<E> &ctx) {
|
||||
return 0x406;
|
||||
}
|
||||
|
||||
} // namespace mold
|
||||
+4
-1
@@ -718,7 +718,8 @@ std::vector<std::string> parse_nonpositional_args(Context<E> &ctx) {
|
||||
<< " elf64briscv\n elf32lriscv\n elf32briscv\n"
|
||||
<< " elf32ppc\n elf64ppc\n elf64lppc\n elf64_s390\n"
|
||||
<< " elf64_sparc\n m68kelf\n shlelf_linux\n"
|
||||
<< " shelf_linux\n elf64loongarch\n elf32loongarch";
|
||||
<< " shelf_linux\n elf64loongarch\n elf32loongarch\n"
|
||||
<< " arclinux";
|
||||
version_shown = true;
|
||||
} else if (read_arg("mllvm")) {
|
||||
ctx.arg.plugin_opt.emplace_back(arg);
|
||||
@@ -761,6 +762,8 @@ std::vector<std::string> parse_nonpositional_args(Context<E> &ctx) {
|
||||
ctx.arg.emulation = LOONGARCH64::name;
|
||||
} else if (arg == "elf32loongarch") {
|
||||
ctx.arg.emulation = LOONGARCH32::name;
|
||||
} else if (arg == "arclinux") {
|
||||
ctx.arg.emulation = ARC::name;
|
||||
} else {
|
||||
Fatal(ctx) << "unknown -m argument: " << arg;
|
||||
}
|
||||
|
||||
+69
@@ -1038,4 +1038,73 @@ std::string rel_to_string<LOONGARCH32>(u32 r_type) {
|
||||
return rel_to_string<LOONGARCH64>(r_type);
|
||||
}
|
||||
|
||||
template <>
|
||||
std::string rel_to_string<ARC>(u32 r_type) {
|
||||
switch (r_type) {
|
||||
CASE(R_ARC_8);
|
||||
CASE(R_ARC_16);
|
||||
CASE(R_ARC_24);
|
||||
CASE(R_ARC_32);
|
||||
CASE(R_ARC_N8);
|
||||
CASE(R_ARC_N16);
|
||||
CASE(R_ARC_N24);
|
||||
CASE(R_ARC_N32);
|
||||
CASE(R_ARC_SDA);
|
||||
CASE(R_ARC_SECTOFF);
|
||||
CASE(R_ARC_S21H_PCREL);
|
||||
CASE(R_ARC_S21W_PCREL);
|
||||
CASE(R_ARC_S25H_PCREL);
|
||||
CASE(R_ARC_S25W_PCREL);
|
||||
CASE(R_ARC_SDA32);
|
||||
CASE(R_ARC_SDA_LDST);
|
||||
CASE(R_ARC_SDA_LDST1);
|
||||
CASE(R_ARC_SDA_LDST2);
|
||||
CASE(R_ARC_SDA16_LD);
|
||||
CASE(R_ARC_SDA16_LD1);
|
||||
CASE(R_ARC_SDA16_LD2);
|
||||
CASE(R_ARC_S13_PCREL);
|
||||
CASE(R_ARC_W);
|
||||
CASE(R_ARC_32_ME);
|
||||
CASE(R_ARC_32_ME_S);
|
||||
CASE(R_ARC_N32_ME);
|
||||
CASE(R_ARC_SECTOFF_ME);
|
||||
CASE(R_ARC_SDA32_ME);
|
||||
CASE(R_ARC_W_ME);
|
||||
CASE(R_ARC_SECTOFF_ME_1);
|
||||
CASE(R_ARC_SECTOFF_ME_2);
|
||||
CASE(R_ARC_SECTOFF_1);
|
||||
CASE(R_ARC_SECTOFF_2);
|
||||
CASE(R_ARC_SDA_12);
|
||||
CASE(R_ARC_SDA16_ST2);
|
||||
CASE(R_ARC_32_PCREL);
|
||||
CASE(R_ARC_PC32);
|
||||
CASE(R_ARC_GOT32);
|
||||
CASE(R_ARC_GOTPC32);
|
||||
CASE(R_ARC_PLT32);
|
||||
CASE(R_ARC_COPY);
|
||||
CASE(R_ARC_GLOB_DAT);
|
||||
CASE(R_ARC_JMP_SLOT);
|
||||
CASE(R_ARC_RELATIVE);
|
||||
CASE(R_ARC_GOTOFF);
|
||||
CASE(R_ARC_GOTPC);
|
||||
CASE(R_ARC_S21W_PCREL_PLT);
|
||||
CASE(R_ARC_S25H_PCREL_PLT);
|
||||
CASE(R_ARC_JLI_SECTOFF);
|
||||
CASE(R_ARC_TLS_DTPMOD);
|
||||
CASE(R_ARC_TLS_TPOFF);
|
||||
CASE(R_ARC_TLS_GD_GOT);
|
||||
CASE(R_ARC_TLS_GD_LD);
|
||||
CASE(R_ARC_TLS_GD_CALL);
|
||||
CASE(R_ARC_TLS_IE_GOT);
|
||||
CASE(R_ARC_TLS_DTPOFF);
|
||||
CASE(R_ARC_TLS_DTPOFF_S9);
|
||||
CASE(R_ARC_TLS_LE_S9);
|
||||
CASE(R_ARC_TLS_LE_32);
|
||||
CASE(R_ARC_S25W_PCREL_PLT);
|
||||
CASE(R_ARC_S21H_PCREL_PLT);
|
||||
CASE(R_ARC_NPS_CMEM16);
|
||||
}
|
||||
return unknown_type(r_type);
|
||||
}
|
||||
|
||||
} // namespace mold
|
||||
@@ -28,6 +28,7 @@ struct SH4LE;
|
||||
struct SH4BE;
|
||||
struct LOONGARCH64;
|
||||
struct LOONGARCH32;
|
||||
struct ARC;
|
||||
|
||||
template <typename E> struct ElfSym;
|
||||
template <typename E> struct ElfShdr;
|
||||
@@ -88,6 +89,7 @@ enum : u32 {
|
||||
SHT_HIOS = 0x6fffffff,
|
||||
SHT_X86_64_UNWIND = 0x70000001,
|
||||
SHT_ARM_EXIDX = 0x70000001,
|
||||
SHT_ARC_ATTRIBUTES = 0x70000001,
|
||||
SHT_ARM_ATTRIBUTES = 0x70000003,
|
||||
SHT_RISCV_ATTRIBUTES = 0x70000003,
|
||||
SHT_LOUSER = 0x80000000,
|
||||
@@ -235,6 +237,7 @@ enum : u32 {
|
||||
EM_SPARC64 = 43,
|
||||
EM_X86_64 = 62,
|
||||
EM_AARCH64 = 183,
|
||||
EM_ARC_COMPACT2 = 195,
|
||||
EM_RISCV = 243,
|
||||
EM_LOONGARCH = 258,
|
||||
};
|
||||
@@ -1362,6 +1365,71 @@ enum : u32 {
|
||||
R_LARCH_TLS_DESC_PCREL20_S2 = 126,
|
||||
};
|
||||
|
||||
enum : u32 {
|
||||
R_ARC_8 = 1,
|
||||
R_ARC_16 = 2,
|
||||
R_ARC_24 = 3,
|
||||
R_ARC_32 = 4,
|
||||
R_ARC_N8 = 8,
|
||||
R_ARC_N16 = 9,
|
||||
R_ARC_N24 = 10,
|
||||
R_ARC_N32 = 11,
|
||||
R_ARC_SDA = 12,
|
||||
R_ARC_SECTOFF = 13,
|
||||
R_ARC_S21H_PCREL = 14,
|
||||
R_ARC_S21W_PCREL = 15,
|
||||
R_ARC_S25H_PCREL = 16,
|
||||
R_ARC_S25W_PCREL = 17,
|
||||
R_ARC_SDA32 = 18,
|
||||
R_ARC_SDA_LDST = 19,
|
||||
R_ARC_SDA_LDST1 = 20,
|
||||
R_ARC_SDA_LDST2 = 21,
|
||||
R_ARC_SDA16_LD = 22,
|
||||
R_ARC_SDA16_LD1 = 23,
|
||||
R_ARC_SDA16_LD2 = 24,
|
||||
R_ARC_S13_PCREL = 25,
|
||||
R_ARC_W = 26,
|
||||
R_ARC_32_ME = 27,
|
||||
R_ARC_32_ME_S = 105,
|
||||
R_ARC_N32_ME = 28,
|
||||
R_ARC_SECTOFF_ME = 29,
|
||||
R_ARC_SDA32_ME = 30,
|
||||
R_ARC_W_ME = 31,
|
||||
R_ARC_SECTOFF_ME_1 = 41,
|
||||
R_ARC_SECTOFF_ME_2 = 42,
|
||||
R_ARC_SECTOFF_1 = 43,
|
||||
R_ARC_SECTOFF_2 = 44,
|
||||
R_ARC_SDA_12 = 45,
|
||||
R_ARC_SDA16_ST2 = 48,
|
||||
R_ARC_32_PCREL = 49,
|
||||
R_ARC_PC32 = 50,
|
||||
R_ARC_GOT32 = 59,
|
||||
R_ARC_GOTPC32 = 51,
|
||||
R_ARC_PLT32 = 52,
|
||||
R_ARC_COPY = 53,
|
||||
R_ARC_GLOB_DAT = 54,
|
||||
R_ARC_JMP_SLOT = 55,
|
||||
R_ARC_RELATIVE = 56,
|
||||
R_ARC_GOTOFF = 57,
|
||||
R_ARC_GOTPC = 58,
|
||||
R_ARC_S21W_PCREL_PLT = 60,
|
||||
R_ARC_S25H_PCREL_PLT = 61,
|
||||
R_ARC_JLI_SECTOFF = 63,
|
||||
R_ARC_TLS_DTPMOD = 66,
|
||||
R_ARC_TLS_TPOFF = 68,
|
||||
R_ARC_TLS_GD_GOT = 69,
|
||||
R_ARC_TLS_GD_LD = 70,
|
||||
R_ARC_TLS_GD_CALL = 71,
|
||||
R_ARC_TLS_IE_GOT = 72,
|
||||
R_ARC_TLS_DTPOFF = 67,
|
||||
R_ARC_TLS_DTPOFF_S9 = 73,
|
||||
R_ARC_TLS_LE_S9 = 74,
|
||||
R_ARC_TLS_LE_32 = 75,
|
||||
R_ARC_S25W_PCREL_PLT = 76,
|
||||
R_ARC_S21H_PCREL_PLT = 77,
|
||||
R_ARC_NPS_CMEM16 = 78,
|
||||
};
|
||||
|
||||
// Returns true if a given relocation is of type used for direct
|
||||
// function call.
|
||||
template <typename E>
|
||||
@@ -1825,6 +1893,7 @@ template <typename E> concept is_sh4le = std::same_as<E, SH4LE>;
|
||||
template <typename E> concept is_sh4be = std::same_as<E, SH4BE>;
|
||||
template <typename E> concept is_loongarch64 = std::same_as<E, LOONGARCH64>;
|
||||
template <typename E> concept is_loongarch32 = std::same_as<E, LOONGARCH32>;
|
||||
template <typename E> concept is_arc = std::same_as<E, ARC>;
|
||||
|
||||
template <typename E> concept is_x86 = is_x86_64<E> || is_i386<E>;
|
||||
template <typename E> concept is_arm64 = is_arm64le<E> || is_arm64be<E>;
|
||||
@@ -2228,4 +2297,27 @@ struct LOONGARCH32 {
|
||||
static constexpr u32 R_FUNCALL[] = { R_LARCH_B26, R_LARCH_CALL36 };
|
||||
};
|
||||
|
||||
struct ARC {
|
||||
static constexpr std::string_view name = "arc";
|
||||
static constexpr bool is_64 = false;
|
||||
static constexpr bool is_le = true;
|
||||
static constexpr bool is_rela = true;
|
||||
static constexpr u32 page_size = 8192;
|
||||
static constexpr u32 e_machine = EM_ARC_COMPACT2;
|
||||
static constexpr u32 plt_hdr_size = 24;
|
||||
static constexpr u32 plt_size = 16;
|
||||
static constexpr u32 pltgot_size = 16;
|
||||
static constexpr u8 filler[] = { 0, 0, 0, 0 };
|
||||
|
||||
static constexpr u32 R_COPY = R_ARC_COPY;
|
||||
static constexpr u32 R_GLOB_DAT = R_ARC_GLOB_DAT;
|
||||
static constexpr u32 R_JUMP_SLOT = R_ARC_JMP_SLOT;
|
||||
static constexpr u32 R_ABS = R_ARC_32;
|
||||
static constexpr u32 R_RELATIVE = R_ARC_RELATIVE;
|
||||
static constexpr u32 R_DTPOFF = R_ARC_TLS_DTPOFF;
|
||||
static constexpr u32 R_TPOFF = R_ARC_TLS_TPOFF;
|
||||
static constexpr u32 R_DTPMOD = R_ARC_TLS_DTPMOD;
|
||||
static constexpr u32 R_FUNCALL[] = { R_ARC_S25W_PCREL_PLT };
|
||||
};
|
||||
|
||||
} // namespace mold
|
||||
@@ -160,6 +160,8 @@ static std::string_view get_elf_type(u8 *buf) {
|
||||
return is_le ? SH4LE::name : SH4BE::name;
|
||||
case EM_LOONGARCH:
|
||||
return is_64 ? LOONGARCH64::name : LOONGARCH32::name;
|
||||
case EM_ARC_COMPACT2:
|
||||
return ARC::name;
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
|
||||
@@ -317,6 +317,10 @@ void ObjectFile<E>::initialize_sections(Context<E> &ctx) {
|
||||
}
|
||||
}
|
||||
|
||||
if constexpr (is_arc<E>)
|
||||
if (shdr.sh_type == SHT_ARC_ATTRIBUTES)
|
||||
continue;
|
||||
|
||||
switch (shdr.sh_type) {
|
||||
case SHT_GROUP: {
|
||||
// Get the signature of this section group.
|
||||
|
||||
+7
-1
@@ -1808,6 +1808,12 @@ public:
|
||||
|
||||
template <> u64 get_eflags(Context<PPC64V2> &ctx);
|
||||
|
||||
//
|
||||
// arch-arc.cc
|
||||
//
|
||||
|
||||
template <> u64 get_eflags(Context<ARC> &ctx);
|
||||
|
||||
//
|
||||
// main.cc
|
||||
//
|
||||
@@ -1928,7 +1934,7 @@ struct ContextExtras<SPARC64> {
|
||||
template <typename E>
|
||||
struct Context {
|
||||
Context() {
|
||||
arg.entry = get_symbol(*this, "_start");
|
||||
arg.entry = get_symbol(*this, is_arc<E> ? "__start" : "_start");
|
||||
arg.fini = get_symbol(*this, "_fini");
|
||||
arg.init = get_symbol(*this, "_init");
|
||||
|
||||
|
||||
@@ -56,6 +56,8 @@ int redo_main(Context<E> &ctx, int argc, char **argv) {
|
||||
return mold_main<LOONGARCH32>(argc, argv);
|
||||
if (target == LOONGARCH64::name)
|
||||
return mold_main<LOONGARCH64>(argc, argv);
|
||||
if (target == ARC::name)
|
||||
return mold_main<ARC>(argc, argv);
|
||||
abort();
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -162,7 +162,7 @@ u64 get_tp_addr(const ElfPhdr<E> &phdr) {
|
||||
// and %a0/%a1 on s390x) refers to past the end of the TLS block for
|
||||
// historical reasons. TLVs are accessed with negative offsets from TP.
|
||||
return align_to(phdr.p_vaddr + phdr.p_memsz, phdr.p_align);
|
||||
} else if constexpr (is_arm<E> || is_sh4<E>) {
|
||||
} else if constexpr (is_arm<E> || is_sh4<E> || is_arc<E>) {
|
||||
// On ARM and SH4, the runtime appends two words at the beginning
|
||||
// of TLV template image when copying TLVs to the TLS block, so we need
|
||||
// to offset it.
|
||||
|
||||
+7
-2
@@ -31,7 +31,7 @@ endif()
|
||||
if(MOLD_ENABLE_QEMU_TESTS)
|
||||
list(APPEND QEMU_ARCHS
|
||||
x86_64 i386 arm aarch64 aarch64_be ppc ppc64 ppc64le sparc64 sh4 sh4eb
|
||||
s390x riscv64 riscv32 m68k loongarch64)
|
||||
s390x riscv64 riscv32 m68k loongarch64 arc)
|
||||
|
||||
LIST(APPEND TRIPLES
|
||||
x86_64-linux-gnu
|
||||
@@ -49,7 +49,8 @@ if(MOLD_ENABLE_QEMU_TESTS)
|
||||
sh4aeb-linux-gnu
|
||||
riscv32-linux-gnu
|
||||
m68k-linux-gnu
|
||||
loongarch64-linux-gnu)
|
||||
loongarch64-linux-gnu
|
||||
arc-linux-gnu)
|
||||
|
||||
foreach(ARCH IN LISTS QEMU_ARCHS)
|
||||
find_program(HAS_qemu-${ARCH} qemu-${ARCH})
|
||||
@@ -184,3 +185,7 @@ endif()
|
||||
if(${MACHINE} STREQUAL "loongarch64" OR (HAS_qemu-loongarch64 AND HAS_loongarch64-linux-gnu-gcc))
|
||||
add_target(loongarch64 loongarch64-linux-gnu)
|
||||
endif()
|
||||
|
||||
if(${MACHINE} STREQUAL "arc" OR (HAS_qemu-loongarch64 AND HAS_arc-linux-gnu-gcc))
|
||||
add_target(arc arc-linux-gnu)
|
||||
endif()
|
||||
Reference in new issue
Block a user