From 0664de05ed2db3d39041e2d51d19622a8ef4fb0f Mon Sep 17 00:00:00 2001 From: Nick Desaulniers Date: Fri, 14 May 2021 20:34:21 -0700 Subject: [PATCH] initial support for PPC64LE (#360) * initial support for PPC64LE See also: https://openpowerfoundation.org/wp-content/uploads/2016/03/ABI64BitOpenPOWERv1.1_16July2015_pub4.pdf 3.4.1 Symbol Values 3.5.3 Relocation Types Table Fixes #317 Signed-off-by: Nick Desaulniers * remove references to LLVM_ADDR_SIG --- elftools/elf/constants.py | 4 + elftools/elf/descriptions.py | 26 +++- elftools/elf/enums.py | 131 ++++++++++++++++++ elftools/elf/relocation.py | 14 +- elftools/elf/structs.py | 5 +- scripts/readelf.py | 10 +- .../powerpc64-relocs-le.o.elf | Bin 0 -> 2912 bytes test/testfiles_for_readelf/powerpc64-relocs.c | 16 +++ 8 files changed, 196 insertions(+), 10 deletions(-) create mode 100644 test/testfiles_for_readelf/powerpc64-relocs-le.o.elf create mode 100644 test/testfiles_for_readelf/powerpc64-relocs.c diff --git a/elftools/elf/constants.py b/elftools/elf/constants.py index 2dc5071..fc55aac 100644 --- a/elftools/elf/constants.py +++ b/elftools/elf/constants.py @@ -27,6 +27,10 @@ class E_FLAGS(object): EF_ARM_ABI_FLOAT_SOFT=0x00000200 EF_ARM_ABI_FLOAT_HARD=0x00000400 + EF_PPC64_ABI_V0=0 + EF_PPC64_ABI_V1=1 + EF_PPC64_ABI_V2=2 + EF_MIPS_NOREORDER=1 EF_MIPS_PIC=2 EF_MIPS_CPIC=4 diff --git a/elftools/elf/descriptions.py b/elftools/elf/descriptions.py index 94da823..82fdff6 100644 --- a/elftools/elf/descriptions.py +++ b/elftools/elf/descriptions.py @@ -9,8 +9,8 @@ from .enums import ( ENUM_D_TAG, ENUM_E_VERSION, ENUM_P_TYPE_BASE, ENUM_SH_TYPE_BASE, ENUM_RELOC_TYPE_i386, ENUM_RELOC_TYPE_x64, - ENUM_RELOC_TYPE_ARM, ENUM_RELOC_TYPE_AARCH64, ENUM_RELOC_TYPE_MIPS, - ENUM_ATTR_TAG_ARM, ENUM_DT_FLAGS, ENUM_DT_FLAGS_1) + ENUM_RELOC_TYPE_ARM, ENUM_RELOC_TYPE_AARCH64, ENUM_RELOC_TYPE_PPC64, + ENUM_RELOC_TYPE_MIPS, ENUM_ATTR_TAG_ARM, ENUM_DT_FLAGS, ENUM_DT_FLAGS_1) from .constants import ( P_FLAGS, RH_FLAGS, SH_FLAGS, SUNW_SYMINFO_FLAGS, VER_FLAGS) from ..common.py3compat import iteritems @@ -84,7 +84,7 @@ def describe_sh_type(x): return _DESCR_SH_TYPE.get(x) elif (x >= ENUM_SH_TYPE_BASE['SHT_LOOS'] and x < ENUM_SH_TYPE_BASE['SHT_GNU_versym']): - return 'loos+%lx' % (x - ENUM_SH_TYPE_BASE['SHT_LOOS']) + return 'loos+0x%lx' % (x - ENUM_SH_TYPE_BASE['SHT_LOOS']) else: return _unknown @@ -98,8 +98,9 @@ def describe_sh_flags(x): SH_FLAGS.SHF_GROUP, SH_FLAGS.SHF_TLS, SH_FLAGS.SHF_MASKOS, SH_FLAGS.SHF_EXCLUDE): s += _DESCR_SH_FLAGS[flag] if (x & flag) else '' - if x & SH_FLAGS.SHF_MASKPROC: - s += 'p' + if not x & SH_FLAGS.SHF_EXCLUDE: + if x & SH_FLAGS.SHF_MASKPROC: + s += 'p' return s @@ -115,6 +116,17 @@ def describe_symbol_visibility(x): return _DESCR_ST_VISIBILITY.get(x, _unknown) +def describe_symbol_local(x): + return '[: ' + str(1 << x) + ']' + + +def describe_symbol_other(x): + vis = describe_symbol_visibility(x['visibility']) + if x['local'] > 1 and x['local'] < 7: + return vis + ' ' + describe_symbol_local(x['local']) + return vis + + def describe_symbol_shndx(x): return _DESCR_ST_SHNDX.get(x, '%3s' % x) @@ -129,6 +141,8 @@ def describe_reloc_type(x, elffile): return _DESCR_RELOC_TYPE_ARM.get(x, _unknown) elif arch == 'AArch64': return _DESCR_RELOC_TYPE_AARCH64.get(x, _unknown) + elif arch == '64-bit PowerPC': + return _DESCR_RELOC_TYPE_PPC64.get(x, _unknown) elif arch == 'MIPS': return _DESCR_RELOC_TYPE_MIPS.get(x, _unknown) else: @@ -303,6 +317,7 @@ _DESCR_E_MACHINE = dict( EM_AARCH64='AArch64', EM_BLACKFIN='Analog Devices Blackfin', EM_PPC='PowerPC', + EM_PPC64='PowerPC64', RESERVED='RESERVED', ) @@ -545,6 +560,7 @@ _DESCR_RELOC_TYPE_i386 = _reverse_dict(ENUM_RELOC_TYPE_i386) _DESCR_RELOC_TYPE_x64 = _reverse_dict(ENUM_RELOC_TYPE_x64) _DESCR_RELOC_TYPE_ARM = _reverse_dict(ENUM_RELOC_TYPE_ARM) _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) _low_priority_D_TAG = ( diff --git a/elftools/elf/enums.py b/elftools/elf/enums.py index bebf7a7..6be988c 100644 --- a/elftools/elf/enums.py +++ b/elftools/elf/enums.py @@ -461,6 +461,10 @@ ENUM_ST_VISIBILITY = dict( _default_=Pass, ) +ENUM_ST_LOCAL = dict( + _default_=Pass, +) + # st_shndx ENUM_ST_SHNDX = dict( SHN_UNDEF=0, @@ -1146,3 +1150,130 @@ ENUM_ATTR_TAG_ARM = dict( TAG_VIRTUALIZATION_USE=68, TAG_MPEXTENSION_USE_OLD=70, ) + +# https://openpowerfoundation.org/wp-content/uploads/2016/03/ABI64BitOpenPOWERv1.1_16July2015_pub4.pdf +# See 3.5.3 Relocation Types Table. +ENUM_RELOC_TYPE_PPC64 = dict( + R_PPC64_NONE=0, + R_PPC64_ADDR32=1, + R_PPC64_ADDR24=2, + R_PPC64_ADDR16=3, + R_PPC64_ADDR16_LO=4, + R_PPC64_ADDR16_HI=5, + R_PPC64_ADDR16_HA=6, + R_PPC64_ADDR14=7, + R_PPC64_ADDR14_BRTAKEN=8, + R_PPC64_ADDR14_BRNTAKEN=9, + R_PPC64_REL24=10, + R_PPC64_REL14=11, + R_PPC64_REL14_BRTAKEN=12, + R_PPC64_REL14_BRNTAKEN=13, + R_PPC64_GOT16=14, + R_PPC64_GOT16_LO=15, + R_PPC64_GOT16_HI=16, + R_PPC64_GOT16_HA=17, + R_PPC64_COPY=19, + R_PPC64_GLOB_DAT=20, + R_PPC64_JMP_SLOT=21, + R_PPC64_RELATIVE=22, + R_PPC64_UADDR32=24, + R_PPC64_UADDR16=25, + R_PPC64_REL32=26, + R_PPC64_PLT32=27, + R_PPC64_PLTREL32=28, + R_PPC64_PLT16_LO=29, + R_PPC64_PLT16_HI=30, + R_PPC64_PLT16_HA=31, + R_PPC64_SECTOFF=33, + R_PPC64_SECTOFF_LO=34, + R_PPC64_SECTOFF_HI=35, + R_PPC64_SECTOFF_HA=36, + R_PPC64_ADDR30=37, + R_PPC64_ADDR64=38, + R_PPC64_ADDR16_HIGHER=39, + R_PPC64_ADDR16_HIGHERA=40, + R_PPC64_ADDR16_HIGHEST=41, + R_PPC64_ADDR16_HIGHESTA=42, + R_PPC64_UADDR64=43, + R_PPC64_REL64=44, + R_PPC64_PLT64=45, + R_PPC64_PLTREL64=46, + R_PPC64_TOC16=47, + R_PPC64_TOC16_LO=48, + R_PPC64_TOC16_HI=49, + R_PPC64_TOC16_HA=50, + R_PPC64_TOC=51, + R_PPC64_PLTGOT16=52, + R_PPC64_PLTGOT16_LO=53, + R_PPC64_PLTGOT16_HI=54, + R_PPC64_PLTGOT16_HA=55, + R_PPC64_ADDR16_DS=56, + R_PPC64_ADDR16_LO_DS=57, + R_PPC64_GOT16_DS=58, + R_PPC64_GOT16_LO_DS=59, + R_PPC64_PLT16_LO_DS=60, + R_PPC64_SECTOFF_DS=61, + R_PPC64_SECTOFF_LO_DS=62, + R_PPC64_TOC16_DS=63, + R_PPC64_TOC16_LO_DS=64, + R_PPC64_PLTGOT16_DS=65, + R_PPC64_PLTGOT16_LO_DS=66, + R_PPC64_TLS=67, + R_PPC64_DTPMOD64=68, + R_PPC64_TPREL16=69, + R_PPC64_TPREL16_LO=70, + R_PPC64_TPREL16_HI=71, + R_PPC64_TPREL16_HA=72, + R_PPC64_TPREL64=73, + R_PPC64_DTPREL16=74, + R_PPC64_DTPREL16_LO=75, + R_PPC64_DTPREL16_HI=76, + R_PPC64_DTPREL16_HA=77, + R_PPC64_DTPREL64=78, + R_PPC64_GOT_TLSGD16=79, + R_PPC64_GOT_TLSGD16_LO=80, + R_PPC64_GOT_TLSGD16_HI=81, + R_PPC64_GOT_TLSGD16_HA=82, + R_PPC64_GOT_TLSLD16=83, + R_PPC64_GOT_TLSLD16_LO=84, + R_PPC64_GOT_TLSLD16_HI=85, + R_PPC64_GOT_TLSLD16_HA=86, + R_PPC64_GOT_TPREL16_DS=87, + R_PPC64_GOT_TPREL16_LO_DS=88, + R_PPC64_GOT_TPREL16_HI=89, + R_PPC64_GOT_TPREL16_HA=90, + R_PPC64_GOT_DTPREL16_DS=91, + R_PPC64_GOT_DTPREL16_LO_DS=92, + R_PPC64_GOT_DTPREL16_HI=93, + R_PPC64_GOT_DTPREL16_HA=94, + R_PPC64_TPREL16_DS=95, + R_PPC64_TPREL16_LO_DS=96, + R_PPC64_TPREL16_HIGHER=97, + R_PPC64_TPREL16_HIGHERA=98, + R_PPC64_TPREL16_HIGHEST=99, + R_PPC64_TPREL16_HIGHESTA=100, + R_PPC64_DTPREL16_DS=101, + R_PPC64_DTPREL16_LO_DS=102, + R_PPC64_DTPREL16_HIGHER=103, + R_PPC64_DTPREL16_HIGHERA=104, + R_PPC64_DTPREL16_HIGHEST=105, + R_PPC64_DTPREL16_HIGHESTA=106, + R_PPC64_TLSGD=107, + R_PPC64_TLSLD=108, + R_PPC64_TOCSAVE=109, + R_PPC64_ADDR16_HIGH=110, + R_PPC64_ADDR16_HIGHA=111, + R_PPC64_TPREL16_HIGH=112, + R_PPC64_TPREL16_HIGHA=113, + R_PPC64_DTPREL16_HIGH=114, + R_PPC64_DTPREL16_HIGHA=115, + R_PPC64_REL24_NOTOC=116, + R_PPC64_ADDR64_LOCAL=117, + R_PPC64_IRELATIVE=248, + R_PPC64_REL16=249, + R_PPC64_REL16_LO=250, + R_PPC64_REL16_HI=251, + R_PPC64_REL16_HA=252, + R_PPC64_GNU_VTINHERIT=253, + R_PPC64_GNU_VTENTRY=254, +) diff --git a/elftools/elf/relocation.py b/elftools/elf/relocation.py index 427a56f..8ca4ca1 100644 --- a/elftools/elf/relocation.py +++ b/elftools/elf/relocation.py @@ -13,7 +13,8 @@ from ..common.utils import elf_assert, struct_parse from .sections import Section from .enums import ( ENUM_RELOC_TYPE_i386, ENUM_RELOC_TYPE_x64, ENUM_RELOC_TYPE_MIPS, - ENUM_RELOC_TYPE_ARM, ENUM_RELOC_TYPE_AARCH64, ENUM_D_TAG) + ENUM_RELOC_TYPE_ARM, ENUM_RELOC_TYPE_AARCH64, ENUM_RELOC_TYPE_PPC64, + ENUM_D_TAG) class Relocation(object): @@ -175,6 +176,8 @@ class RelocationHandler(object): recipe = self._RELOCATION_RECIPES_ARM.get(reloc_type, None) elif self.elffile.get_machine_arch() == 'AArch64': recipe = self._RELOCATION_RECIPES_AARCH64.get(reloc_type, None) + elif self.elffile.get_machine_arch() == '64-bit PowerPC': + recipe = self._RELOCATION_RECIPES_PPC64.get(reloc_type, None) if recipe is None: raise ELFRelocationError( @@ -269,6 +272,15 @@ class RelocationHandler(object): calc_func=_reloc_calc_sym_plus_value), } + _RELOCATION_RECIPES_PPC64 = { + ENUM_RELOC_TYPE_PPC64['R_PPC64_ADDR32']: _RELOCATION_RECIPE_TYPE( + bytesize=4, has_addend=True, calc_func=_reloc_calc_sym_plus_addend), + ENUM_RELOC_TYPE_PPC64['R_PPC64_REL32']: _RELOCATION_RECIPE_TYPE( + bytesize=4, has_addend=True, calc_func=_reloc_calc_sym_plus_addend_pcrel), + ENUM_RELOC_TYPE_PPC64['R_PPC64_ADDR64']: _RELOCATION_RECIPE_TYPE( + bytesize=8, has_addend=True, calc_func=_reloc_calc_sym_plus_addend), + } + _RELOCATION_RECIPES_X86 = { ENUM_RELOC_TYPE_i386['R_386_NONE']: _RELOCATION_RECIPE_TYPE( bytesize=4, has_addend=False, calc_func=_reloc_calc_identity), diff --git a/elftools/elf/structs.py b/elftools/elf/structs.py index 0c6a809..ee4beac 100644 --- a/elftools/elf/structs.py +++ b/elftools/elf/structs.py @@ -289,7 +289,10 @@ class ELFStructs(object): # st_other is hierarchical. To access the visibility, # use container['st_other']['visibility'] st_other_struct = BitStruct('st_other', - Padding(5), + # https://openpowerfoundation.org/wp-content/uploads/2016/03/ABI64BitOpenPOWERv1.1_16July2015_pub4.pdf + # See 3.4.1 Symbol Values. + Enum(BitField('local', 3), **ENUM_ST_LOCAL), + Padding(2), Enum(BitField('visibility', 3), **ENUM_ST_VISIBILITY)) if self.elfclass == 32: self.Elf_Sym = Struct('Elf_Sym', diff --git a/scripts/readelf.py b/scripts/readelf.py index c298aa2..249d99a 100755 --- a/scripts/readelf.py +++ b/scripts/readelf.py @@ -48,7 +48,7 @@ from elftools.elf.descriptions import ( describe_symbol_type, describe_symbol_bind, describe_symbol_visibility, describe_symbol_shndx, describe_reloc_type, describe_dyn_tag, describe_dt_flags, describe_dt_flags_1, describe_ver_flags, describe_note, - describe_attr_tag_arm + describe_attr_tag_arm, describe_symbol_other ) from elftools.elf.constants import E_FLAGS from elftools.elf.constants import E_FLAGS_MASKS @@ -173,6 +173,10 @@ class ReadElf(object): else: description += ', ' + elif self.elffile['e_machine'] == 'EM_PPC64': + if flags & E_FLAGS.EF_PPC64_ABI_V2: + description += ', abiv2' + elif self.elffile['e_machine'] == "EM_MIPS": if flags & E_FLAGS.EF_MIPS_NOREORDER: description += ", noreorder" @@ -422,7 +426,7 @@ class ReadElf(object): "%5d" % symbol['st_size'] if symbol['st_size'] < 100000 else hex(symbol['st_size']), describe_symbol_type(symbol['st_info']['type']), describe_symbol_bind(symbol['st_info']['bind']), - describe_symbol_visibility(symbol['st_other']['visibility']), + describe_symbol_other(symbol['st_other']), describe_symbol_shndx(self._get_symbol_shndx(symbol, nsym, section_index)), @@ -1143,7 +1147,7 @@ class ReadElf(object): # readelf doesn't print the state after end_sequence # instructions. I think it's a bug but to be compatible # I don't print them too. - if lineprogram['version'] < 4: + if lineprogram['version'] < 4 or self.elffile['e_machine'] == 'EM_PPC64': self._emitline('%-35s %11d %18s' % ( bytes2str(lineprogram['file_entry'][state.file - 1].name), state.line, diff --git a/test/testfiles_for_readelf/powerpc64-relocs-le.o.elf b/test/testfiles_for_readelf/powerpc64-relocs-le.o.elf new file mode 100644 index 0000000000000000000000000000000000000000..9d67c1ffe8a4141d7f16439e48df6e8cc2592327 GIT binary patch literal 2912 zcmc&$&2Jl35TEsWjT0v(aSF5)!L}3#McLR+8YgWo1_D1VX znnFY@S`Kg_961&BP*ohcR2&dg{1ZLGEfSY3oVyU0=zYUH<8}h+5P?T7$`drb`R~WXHIS8 zVRI`FKX(8sXmfLW5^nDRIGue*?G2P$nCBe~bs6#PB;4v;&ZEvCOY|X*uwh4#k zG3GYL{^PEi-q4}59HwWcj4Q8XCp0xX_T0hjxRS$ZCJY2~DRaM?J)Sv{dF{aYiBksv zR1Fdgou2?m9sxD`W+s!tKp$XBh5^&z+DAC}UeQ67mLF0Fx#Ce*8M%mDO?;E@X;CyS z3Cnf+nts}CTdR#$-SykL-LP6UeGR*Huca4ejJ%Q8Cu{Y<#CB!1V%T2uc%!k_oF+E4 z;(J$JJ1}rix9nqu;`~CsGF!^e6sxxD7UoJ;DPOcIg;~cswosTUm5MX=>#*Wocl{N6 zZg$Fd8=l=ZY?!uMj_=i-!t}}ww^0o|uhE_k+;$MMYQ5pM%T>=W`>y5SI8;3k>a74Q z_@CB5n;D}q?kk^Mgyj07a&Sa}{fJQ`>JU4dHE%29i=QoyzVsogNjOSeQ66VUK|w+d zo6>K8a0p}lM|7=ZsU02jW0V<#;Xl+kkn_=|C& zA7LAsm&Sb(liW8^#&IkLA<>G5xKH8&_vJX37&lSI<8b*3E0)SOB*asvQx$V0JVy*k z;A@cz&$1+3#3bnX7*27%Wc@{!ucGXo0>B#s@CC+2-XB>%C*coRe^0`HVqFNz8^0|t z@Bqy>KA#ff@;rxz!EoHlYOQQlD!#i029^}d2;B7ms8%&yED~(d4t%Isepovqv&ggF zs(N6wyudZiEx$k24lMf`7*yZNmg8V0tZ~%Hyisqt47gXyRo`j~HSp|yZ`Z)YfmH#c zeWOXzu>uQ>OYgo-m-#=^9rTai7ZL6-AHKZbbZ&9lhl+exXxt=*)CqZy$#3#$9E#sd zVQDgWkAZQNbe`f3in>U-kd3Zp2=|*me&9oT z6bYdD(|eWY|1x3}GmkA!Wlr>K9K^oJFC^Xbe*TB~@?ZZKe|mQ!R^0Sk_K#!KmusC&@J|t=Imy$#$AG-A!XI5iqPo{F|D!(n zsg??Vk^d@U@}5xOhn)XoQeq_Ax;WM^f12N)$V2O=ub-Ts{sYvdUHVh&VC$03{$gLq bpGeOCJz~NpG+;K*2O9k_Mt=0Qmh=Au{j3i+ literal 0 HcmV?d00001 diff --git a/test/testfiles_for_readelf/powerpc64-relocs.c b/test/testfiles_for_readelf/powerpc64-relocs.c new file mode 100644 index 0000000..fe5c3e8 --- /dev/null +++ b/test/testfiles_for_readelf/powerpc64-relocs.c @@ -0,0 +1,16 @@ +/* This source was compiled for ppc64le. + clang --target=powerpc64le -c -o powerpc64-relocs-le.o.elf powerpc64-relocs.c -g +*/ + +extern struct { + int i, j; +} data; + +extern int bar (void); + +int +foo (int a) +{ + data.i += a; + data.j -= bar(); +} -- 2.30.2