EF_RISCV_RVE=0x00000008
EF_RISCV_TSO=0x00000010
- EF_LOONGARCH_ABI=0x000000C0
- EF_LOONGARCH_ABI_V0=0x00000000
- EF_LOONGARCH_ABI_V1=0x00000040
- EF_LOONGARCH_FLOAT_ABI=0x00000003
- EF_LOONGARCH_FLOAT_ABI_SOFT=0x00000001
- EF_LOONGARCH_FLOAT_ABI_SINGLE=0x00000002
- EF_LOONGARCH_FLOAT_ABI_DOUBLE=0x00000003
+ EF_LOONGARCH_OBJABI_MASK=0x000000C0
+ EF_LOONGARCH_OBJABI_V0=0x00000000
+ EF_LOONGARCH_OBJABI_V1=0x00000040
+ EF_LOONGARCH_ABI_MODIFIER_MASK=0x00000007
+ EF_LOONGARCH_ABI_SOFT_FLOAT=0x00000001
+ EF_LOONGARCH_ABI_SINGLE_FLOAT=0x00000002
+ EF_LOONGARCH_ABI_DOUBLE_FLOAT=0x00000003
+ # The names in the glibc elf.h say "LARCH" instead of "LOONGARCH",
+ # provide these names for users' convenience.
+ EF_LARCH_OBJABI_MASK = EF_LOONGARCH_OBJABI_MASK
+ EF_LARCH_OBJABI_V0 = EF_LOONGARCH_OBJABI_V0
+ EF_LARCH_OBJABI_V1 = EF_LOONGARCH_OBJABI_V1
+ EF_LARCH_ABI_MODIFIER_MASK = EF_LOONGARCH_ABI_MODIFIER_MASK
+ EF_LARCH_ABI_SOFT_FLOAT = EF_LOONGARCH_ABI_SOFT_FLOAT
+ EF_LARCH_ABI_SINGLE_FLOAT = EF_LOONGARCH_ABI_SINGLE_FLOAT
+ EF_LARCH_ABI_DOUBLE_FLOAT = EF_LOONGARCH_ABI_DOUBLE_FLOAT
class E_FLAGS_MASKS(object):
"""Masks to be used for convenience when working with E_FLAGS
ENUM_RELOC_TYPE_i386, ENUM_RELOC_TYPE_x64,
ENUM_RELOC_TYPE_ARM, ENUM_RELOC_TYPE_AARCH64, ENUM_RELOC_TYPE_PPC64,
ENUM_RELOC_TYPE_MIPS, ENUM_ATTR_TAG_ARM, ENUM_ATTR_TAG_RISCV,
- ENUM_DT_FLAGS, ENUM_DT_FLAGS_1)
+ ENUM_RELOC_TYPE_LOONGARCH, ENUM_DT_FLAGS, ENUM_DT_FLAGS_1)
from .constants import (
P_FLAGS, RH_FLAGS, SH_FLAGS, SUNW_SYMINFO_FLAGS, VER_FLAGS)
from ..common.utils import bytes2hex
return _DESCR_RELOC_TYPE_PPC64.get(x, _unknown)
elif arch == 'MIPS':
return _DESCR_RELOC_TYPE_MIPS.get(x, _unknown)
+ elif arch == 'LoongArch':
+ return _DESCR_RELOC_TYPE_LOONGARCH.get(x, _unknown)
else:
return 'unrecognized: %-7x' % (x & 0xFFFFFFFF)
_DESCR_RELOC_TYPE_AARCH64 = _reverse_dict(ENUM_RELOC_TYPE_AARCH64)
_DESCR_RELOC_TYPE_PPC64 = _reverse_dict(ENUM_RELOC_TYPE_PPC64)
_DESCR_RELOC_TYPE_MIPS = _reverse_dict(ENUM_RELOC_TYPE_MIPS)
+_DESCR_RELOC_TYPE_LOONGARCH = _reverse_dict(ENUM_RELOC_TYPE_LOONGARCH)
_low_priority_D_TAG = (
# these are 'meta-tags' marking semantics of numeric ranges of the enum
'EM_RISCV' : 'RISC-V',
'EM_BPF' : 'Linux BPF - in-kernel virtual machine',
'EM_CSKY' : 'C-SKY',
+ 'EM_LOONGARCH' : 'LoongArch',
'EM_FRV' : 'Fujitsu FR-V'
}
_default_=Pass,
)
+# https://github.com/loongson/la-abi-specs/blob/release/laelf.adoc
+ENUM_RELOC_TYPE_LOONGARCH = dict(
+ R_LARCH_NONE=0,
+ R_LARCH_32=1,
+ R_LARCH_64=2,
+ R_LARCH_RELATIVE=3,
+ R_LARCH_COPY=4,
+ R_LARCH_JUMP_SLOT=5,
+ R_LARCH_TLS_DTPMOD32=6,
+ R_LARCH_TLS_DTPMOD64=7,
+ R_LARCH_TLS_DTPREL32=8,
+ R_LARCH_TLS_DTPREL64=9,
+ R_LARCH_TLS_TPREL32=10,
+ R_LARCH_TLS_TPREL64=11,
+ R_LARCH_IRELATIVE=12,
+ R_LARCH_MARK_LA=20,
+ R_LARCH_MARK_PCREL=21,
+ R_LARCH_SOP_PUSH_PCREL=22,
+ R_LARCH_SOP_PUSH_ABSOLUTE=23,
+ R_LARCH_SOP_PUSH_DUP=24,
+ R_LARCH_SOP_PUSH_GPREL=25,
+ R_LARCH_SOP_PUSH_TLS_TPREL=26,
+ R_LARCH_SOP_PUSH_TLS_GOT=27,
+ R_LARCH_SOP_PUSH_TLS_GD=28,
+ R_LARCH_SOP_PUSH_PLT_PCREL=29,
+ R_LARCH_SOP_ASSERT=30,
+ R_LARCH_SOP_NOT=31,
+ R_LARCH_SOP_SUB=32,
+ R_LARCH_SOP_SL=33,
+ R_LARCH_SOP_SR=34,
+ R_LARCH_SOP_ADD=35,
+ R_LARCH_SOP_AND=36,
+ R_LARCH_SOP_IF_ELSE=37,
+ R_LARCH_SOP_POP_32_S_10_5=38,
+ R_LARCH_SOP_POP_32_U_10_12=39,
+ R_LARCH_SOP_POP_32_S_10_12=40,
+ R_LARCH_SOP_POP_32_S_10_16=41,
+ R_LARCH_SOP_POP_32_S_10_16_S2=42,
+ R_LARCH_SOP_POP_32_S_5_20=43,
+ R_LARCH_SOP_POP_32_S_0_5_10_16_S2=44,
+ R_LARCH_SOP_POP_32_S_0_10_10_16_S2=45,
+ R_LARCH_SOP_POP_32_U=46,
+ R_LARCH_ADD8=47,
+ R_LARCH_ADD16=48,
+ R_LARCH_ADD24=49,
+ R_LARCH_ADD32=50,
+ R_LARCH_ADD64=51,
+ R_LARCH_SUB8=52,
+ R_LARCH_SUB16=53,
+ R_LARCH_SUB24=54,
+ R_LARCH_SUB32=55,
+ R_LARCH_SUB64=56,
+ R_LARCH_GNU_VTINHERIT=57,
+ R_LARCH_GNU_VTENTRY=58,
+ R_LARCH_B16=64,
+ R_LARCH_B21=65,
+ R_LARCH_B26=66,
+ R_LARCH_ABS_HI20=67,
+ R_LARCH_ABS_LO12=68,
+ R_LARCH_ABS64_LO20=69,
+ R_LARCH_ABS64_HI12=70,
+ R_LARCH_PCALA_HI20=71,
+ R_LARCH_PCALA_LO12=72,
+ R_LARCH_PCALA64_LO20=73,
+ R_LARCH_PCALA64_HI12=74,
+ R_LARCH_GOT_PC_HI20=75,
+ R_LARCH_GOT_PC_LO12=76,
+ R_LARCH_GOT64_PC_LO20=77,
+ R_LARCH_GOT64_PC_HI12=78,
+ R_LARCH_GOT_HI20=79,
+ R_LARCH_GOT_LO12=80,
+ R_LARCH_GOT64_LO20=81,
+ R_LARCH_GOT64_HI12=82,
+ R_LARCH_TLS_LE_HI20=83,
+ R_LARCH_TLS_LE_LO12=84,
+ R_LARCH_TLS_LE64_LO20=85,
+ R_LARCH_TLS_LE64_HI12=86,
+ R_LARCH_TLS_IE_PC_HI20=87,
+ R_LARCH_TLS_IE_PC_LO12=88,
+ R_LARCH_TLS_IE64_PC_LO20=89,
+ R_LARCH_TLS_IE64_PC_HI12=90,
+ R_LARCH_TLS_IE_HI20=91,
+ R_LARCH_TLS_IE_LO12=92,
+ R_LARCH_TLS_IE64_LO20=93,
+ R_LARCH_TLS_IE64_HI12=94,
+ R_LARCH_TLS_LD_PC_HI20=95,
+ R_LARCH_TLS_LD_HI20=96,
+ R_LARCH_TLS_GD_PC_HI20=97,
+ R_LARCH_TLS_GD_HI20=98,
+ R_LARCH_32_PCREL=99,
+ R_LARCH_RELAX=100,
+ R_LARCH_DELETE=101,
+ R_LARCH_ALIGN=102,
+ R_LARCH_PCREL20_S2=103,
+ R_LARCH_CFA=104,
+ R_LARCH_ADD6=105,
+ R_LARCH_SUB6=106,
+ R_LARCH_ADD_ULEB128=107,
+ R_LARCH_SUB_ULEB128=108,
+ R_LARCH_64_PCREL=109,
+ _default_=Pass,
+)
+
# Sunw Syminfo Bound To special values
ENUM_SUNW_SYMINFO_BOUNDTO = dict(
SYMINFO_BT_SELF=0xffff,
from .enums import (
ENUM_RELOC_TYPE_i386, ENUM_RELOC_TYPE_x64, ENUM_RELOC_TYPE_MIPS,
ENUM_RELOC_TYPE_ARM, ENUM_RELOC_TYPE_AARCH64, ENUM_RELOC_TYPE_PPC64,
- ENUM_RELOC_TYPE_BPF, ENUM_D_TAG)
+ ENUM_RELOC_TYPE_BPF, ENUM_RELOC_TYPE_LOONGARCH, ENUM_D_TAG)
from ..construct import Container
recipe = self._RELOCATION_RECIPES_PPC64.get(reloc_type, None)
elif self.elffile.get_machine_arch() == 'Linux BPF - in-kernel virtual machine':
recipe = self._RELOCATION_RECIPES_EBPF.get(reloc_type, None)
+ elif self.elffile.get_machine_arch() == 'LoongArch':
+ if not reloc.is_RELA():
+ raise ELFRelocationError(
+ 'Unexpected REL relocation for LoongArch: %s' % reloc)
+ recipe = self._RELOCATION_RECIPES_LOONGARCH.get(reloc_type, None)
if recipe is None:
raise ELFRelocationError(
value_struct = self.elffile.structs.Elf_word('')
elif recipe.bytesize == 8:
value_struct = self.elffile.structs.Elf_word64('')
+ elif recipe.bytesize == 1:
+ value_struct = self.elffile.structs.Elf_byte('')
+ elif recipe.bytesize == 2:
+ value_struct = self.elffile.structs.Elf_half('')
else:
raise ELFRelocationError('Invalid bytesize %s for relocation' %
recipe.bytesize)
def _reloc_calc_sym_plus_addend_pcrel(value, sym_value, offset, addend=0):
return sym_value + addend - offset
+ def _reloc_calc_value_minus_sym_addend(value, sym_value, offset, addend=0):
+ return value - sym_value - addend
+
def _arm_reloc_calc_sym_plus_value_pcrel(value, sym_value, offset, addend=0):
return sym_value // 4 + value - offset // 4
bytesize=4, has_addend=False, calc_func=_reloc_calc_identity),
}
+ # https://github.com/loongson/la-abi-specs/blob/release/laelf.adoc
+ _RELOCATION_RECIPES_LOONGARCH = {
+ ENUM_RELOC_TYPE_LOONGARCH['R_LARCH_NONE']: _RELOCATION_RECIPE_TYPE(
+ bytesize=4, has_addend=False, calc_func=_reloc_calc_identity),
+ ENUM_RELOC_TYPE_LOONGARCH['R_LARCH_32']: _RELOCATION_RECIPE_TYPE(
+ bytesize=4, has_addend=True,
+ calc_func=_reloc_calc_sym_plus_addend),
+ ENUM_RELOC_TYPE_LOONGARCH['R_LARCH_64']: _RELOCATION_RECIPE_TYPE(
+ bytesize=8, has_addend=True,
+ calc_func=_reloc_calc_sym_plus_addend),
+ ENUM_RELOC_TYPE_LOONGARCH['R_LARCH_ADD8']: _RELOCATION_RECIPE_TYPE(
+ bytesize=1, has_addend=True,
+ calc_func=_reloc_calc_sym_plus_value),
+ ENUM_RELOC_TYPE_LOONGARCH['R_LARCH_SUB8']: _RELOCATION_RECIPE_TYPE(
+ bytesize=1, has_addend=True,
+ calc_func=_reloc_calc_value_minus_sym_addend),
+ ENUM_RELOC_TYPE_LOONGARCH['R_LARCH_ADD16']: _RELOCATION_RECIPE_TYPE(
+ bytesize=2, has_addend=True,
+ calc_func=_reloc_calc_sym_plus_value),
+ ENUM_RELOC_TYPE_LOONGARCH['R_LARCH_SUB16']: _RELOCATION_RECIPE_TYPE(
+ bytesize=2, has_addend=True,
+ calc_func=_reloc_calc_value_minus_sym_addend),
+ ENUM_RELOC_TYPE_LOONGARCH['R_LARCH_ADD32']: _RELOCATION_RECIPE_TYPE(
+ bytesize=4, has_addend=True,
+ calc_func=_reloc_calc_sym_plus_value),
+ ENUM_RELOC_TYPE_LOONGARCH['R_LARCH_SUB32']: _RELOCATION_RECIPE_TYPE(
+ bytesize=4, has_addend=True,
+ calc_func=_reloc_calc_value_minus_sym_addend),
+ ENUM_RELOC_TYPE_LOONGARCH['R_LARCH_ADD64']: _RELOCATION_RECIPE_TYPE(
+ bytesize=8, has_addend=True,
+ calc_func=_reloc_calc_sym_plus_value),
+ ENUM_RELOC_TYPE_LOONGARCH['R_LARCH_SUB64']: _RELOCATION_RECIPE_TYPE(
+ bytesize=8, has_addend=True,
+ calc_func=_reloc_calc_value_minus_sym_addend),
+ ENUM_RELOC_TYPE_LOONGARCH['R_LARCH_32_PCREL']: _RELOCATION_RECIPE_TYPE(
+ bytesize=4, has_addend=True,
+ calc_func=_reloc_calc_sym_plus_addend_pcrel),
+ ENUM_RELOC_TYPE_LOONGARCH['R_LARCH_64_PCREL']: _RELOCATION_RECIPE_TYPE(
+ bytesize=8, has_addend=True,
+ calc_func=_reloc_calc_sym_plus_addend_pcrel),
+ }
+
self.elffile = ELFFile(file)
self.output = output
self._dwarfinfo = self.elffile.get_dwarf_info()
- arches = {"EM_386": "i386", "EM_X86_64": "x86-64", "EM_ARM": "littlearm", "EM_AARCH64": "littleaarch64", "EM_LOONGARCH64": "loongarch64", "EM_RISCV": "littleriscv", "EM_MIPS": "mips"}
+ arches = {"EM_386": "i386", "EM_X86_64": "x86-64", "EM_ARM": "littlearm", "EM_AARCH64": "littleaarch64", "EM_LOONGARCH": "loongarch", "EM_RISCV": "littleriscv", "EM_MIPS": "mips"}
arch = arches[self.elffile['e_machine']]
bits = self.elffile.elfclass
self._emitline("%s: file format elf%d-%s" % (filename, bits, arch))
#-------------------------------------------------------------------------------
import argparse
import os, sys
+import re
import string
import traceback
import itertools
else:
raise ValueError("Can't find the base IP (low_pc) for a CU")
+# Matcher for all control characters, for transforming them into "^X" form when
+# formatting symbol names for display.
+_CONTROL_CHAR_RE = re.compile(r'[\x01-\x1f]')
+
+def _format_symbol_name(s):
+ return _CONTROL_CHAR_RE.sub(lambda match: '^' + chr(0x40 + ord(match[0])), s)
+
class ReadElf(object):
""" display_* methods are used to emit output into the output stream
"""
description += ", quad-float ABI"
elif self.elffile['e_machine'] == "EM_LOONGARCH":
- if (flags & E_FLAGS.EF_LOONGARCH_FLOAT_ABI) == E_FLAGS.EF_LOONGARCH_FLOAT_ABI_SOFT:
+ if (flags & E_FLAGS.EF_LOONGARCH_ABI_MODIFIER_MASK) == E_FLAGS.EF_LOONGARCH_ABI_SOFT_FLOAT:
description += ", SOFT-FLOAT"
- if (flags & E_FLAGS.EF_LOONGARCH_FLOAT_ABI) == E_FLAGS.EF_LOONGARCH_FLOAT_ABI_SINGLE:
+ if (flags & E_FLAGS.EF_LOONGARCH_ABI_MODIFIER_MASK) == E_FLAGS.EF_LOONGARCH_ABI_SINGLE_FLOAT:
description += ", SINGLE-FLOAT"
- if (flags & E_FLAGS.EF_LOONGARCH_FLOAT_ABI) == E_FLAGS.EF_LOONGARCH_FLOAT_ABI_DOUBLE:
+ if (flags & E_FLAGS.EF_LOONGARCH_ABI_MODIFIER_MASK) == E_FLAGS.EF_LOONGARCH_ABI_DOUBLE_FLOAT:
description += ", DOUBLE-FLOAT"
- if (flags & E_FLAGS.EF_LOONGARCH_ABI) == E_FLAGS.EF_LOONGARCH_ABI_V0:
+ if (flags & E_FLAGS.EF_LOONGARCH_OBJABI_MASK) == E_FLAGS.EF_LOONGARCH_OBJABI_V0:
description += ", OBJ-v0"
- if (flags & E_FLAGS.EF_LOONGARCH_ABI) == E_FLAGS.EF_LOONGARCH_ABI_V1:
+ if (flags & E_FLAGS.EF_LOONGARCH_OBJABI_MASK) == E_FLAGS.EF_LOONGARCH_OBJABI_V1:
description += ", OBJ-v1"
return description
describe_symbol_shndx(self._get_symbol_shndx(symbol,
nsym,
section_index)),
- symbol_name,
+ _format_symbol_name(symbol_name),
version_info))
def display_dynamic_tags(self):
self._format_hex(
symbol['st_value'],
fullhex=True, lead0x=False),
- symbol_name))
+ _format_symbol_name(symbol_name)))
if section.is_RELA():
self._emit(' %s %x' % (
'+' if rel['r_addend'] >= 0 else '-',
# Look at the registers the decoded table describes.
# We build reg_order here to match readelf's order. In particular,
- # registers are sorted by their number, and the register matching
- # ra_regnum is always listed last with a special heading.
+ # registers are sorted by their number, so that the register
+ # matching ra_regnum is usually listed last with a special heading.
+ # (LoongArch is a notable exception in that its return register's
+ # DWARF register number is not greater than other GPRs.)
decoded_table = entry.get_decoded()
- reg_order = sorted(filter(
- lambda r: r != ra_regnum,
- decoded_table.reg_order))
+ reg_order = sorted(decoded_table.reg_order)
if len(decoded_table.reg_order):
-
# Headings for the registers
for regnum in reg_order:
+ if regnum == ra_regnum:
+ self._emit('ra ')
+ continue
self._emit('%-6s' % describe_reg_name(regnum))
- self._emitline('ra ')
-
- # Now include ra_regnum in reg_order to print its values
- # similarly to the other registers.
- reg_order.append(ra_regnum)
- else:
- self._emitline()
+ self._emitline()
for line in decoded_table.table:
self._emit(self._format_hex(
--- /dev/null
+/* This source was compiled for LoongArch64.
+ loongarch64-unknown-linux-gnu-gcc -c -o loongarch64-relocs.o.elf loongarch-relocs.c -g
+ Upstream support for LoongArch32 is not yet mature, so it is not covered.
+*/
+
+extern struct {
+ int i, j;
+} data;
+
+extern int bar (void);
+
+int
+foo (int a)
+{
+ data.i += a;
+ data.j -= bar();
+ return 0;
+}