From d6b2913ba0272c0be74670c9da5ded462859e030 Mon Sep 17 00:00:00 2001 From: Andreas Ziegler Date: Mon, 26 Oct 2020 14:07:42 +0100 Subject: [PATCH] hash.py: observe endianness when reading hashes (#338) Reading the hashes from a GNUHashTable didn't properly use the endianness of the underlying ELF file, so looking up hashes would fail if the byte order of the analyzed file did not match the native byte order of the current machine. The test file consists of two functions: int callee(){ return 42; } int caller(){ return callee(); } and was compiled using `aarch64_be-linux-gcc` (version 8.3 on an x86_64 host) with the `-mbig-endian` and `-shared` command line flags. --- elftools/elf/hash.py | 6 ++++-- test/test_hash.py | 14 ++++++++++++++ .../aarch64_be_gnu_hash.so.elf | Bin 0 -> 9608 bytes 3 files changed, 18 insertions(+), 2 deletions(-) create mode 100755 test/testfiles_for_unittests/aarch64_be_gnu_hash.so.elf diff --git a/elftools/elf/hash.py b/elftools/elf/hash.py index 2e8a6fe..c8d1e17 100644 --- a/elftools/elf/hash.py +++ b/elftools/elf/hash.py @@ -119,10 +119,11 @@ class GNUHashTable(object): max_chain_pos = self._chain_pos + \ (max_idx - self.params['symoffset']) * self._wordsize self.elffile.stream.seek(max_chain_pos) + hash_format = 'I' # Walk the chain to its end (lowest bit is set) while True: - cur_hash = struct.unpack('I', self.elffile.stream.read(self._wordsize))[0] + cur_hash = struct.unpack(hash_format, self.elffile.stream.read(self._wordsize))[0] if cur_hash & 1: return max_idx + 1 @@ -150,8 +151,9 @@ class GNUHashTable(object): return None self.elffile.stream.seek(self._chain_pos + (symidx - self.params['symoffset']) * self._wordsize) + hash_format = 'I' while True: - cur_hash = struct.unpack('I', self.elffile.stream.read(self._wordsize))[0] + cur_hash = struct.unpack(hash_format, self.elffile.stream.read(self._wordsize))[0] if cur_hash | 1 == namehash | 1: symbol = self._symboltable.get_symbol(symidx) if name == symbol.name: diff --git a/test/test_hash.py b/test/test_hash.py index 7832a76..2c2ffec 100644 --- a/test/test_hash.py +++ b/test/test_hash.py @@ -99,3 +99,17 @@ class TestGNUHash(unittest.TestCase): symbol_f1 = hash_section.get_symbol('function1_ver1_1') self.assertIsNotNone(symbol_f1) self.assertEqual(symbol_f1['st_value'], int(0x9a2)) + + def test_get_symbol_big_endian(self): + """ Verify we can get a specific symbol from a GNU hash section in a + big-endian file. + """ + with open(os.path.join('test', 'testfiles_for_unittests', + 'aarch64_be_gnu_hash.so.elf'), 'rb') as f: + elf = ELFFile(f) + self.assertFalse(elf.little_endian) + hash_section = elf.get_section_by_name('.gnu.hash') + self.assertIsNotNone(hash_section) + symbol_f1 = hash_section.get_symbol('caller') + self.assertIsNotNone(symbol_f1) + self.assertEqual(symbol_f1['st_value'], int(0x5a4)) diff --git a/test/testfiles_for_unittests/aarch64_be_gnu_hash.so.elf b/test/testfiles_for_unittests/aarch64_be_gnu_hash.so.elf new file mode 100755 index 0000000000000000000000000000000000000000..ed3684495887b192857cccdd6223eff2f11d0830 GIT binary patch literal 9608 zcmeHNYiwLc6`s2fW11#eCoK(4N!C#+rBZe`kJfRZ(6t@M2};t`aZq`Po4dQ$-c|Pz zcGs!hRNzKJssso}sc0qIs;CvDLPGfwMEFwzv?vuIMLePk+9;p`mI{(ll}c8dEZ>XT|3Sh4Wo%p*ABxkzoOA;K^01CUWN8(G=3qJ#c$T|%bQU-+-^bDnXCWf zAZ#PrUPUjoM|Hp91B}4$A#hwDYi|xQ_zlC1>ub3$xla{}n^1zfFT>zIj!b<@^>!k+ zOCJMCwv?zI>KEd4zdGcWhGe+TtN*v?R2_v1H7zUY+)5?dD9eP}NB_XkeKL+dZCkB9#(8M-rFq4ZoV zq_j@U9gsIz@-2}2jXZ@|>fb|iX{F9yZ8YwndMFn7Gipkmd;-`Fd_bvpUQlWT@^tsx zLvwww$8>gSG5c<%e%t-Qz^U#J`o4vH>Ibkt0pI@Fp}BsP)9icg_$&H8-(9BWPNA+N zC(=99j=E2`Yi4K;cviRN*7V%#jmFb|L5{1b;Ug#1&Ucrk=dK<9mF}A>XnQ(3HB9Z1 zzIzR}(s#m%?5qucMkzgSbu=1{ILafygTOrSN#Ntai@+Cve*&HZz6tytGNl+@oX3V$ zWMZAO_EwtOHMgeGxc(~2n~6XoyUpOP0DF-s#gWs9hcTk|sJ<2P=OWLC`%i@qTz>11 zE5K2rcQ*%{O+d1fMDeI?q^I#j=`Q4Ha3tS`c(La~&pQK`-;!8lvy_&4V5tX|dSIys zmU>{R2X5E{ysuQzgKXw7(*Bgvtpu+J4VB~Xw!gf+8vwwD0O8v4Q-NSm?TTr6& z5v4l}MB)a84@>+`=1(*7xyaO4!RE*C;fDz!H`q@1D`akWIL-Pw*7H7}rH=|6KL38` zc#$dN+JZP=3=Ir?I=*S>z~T5vrBcl1y+S!YTB*kCc|YElI9jcY7K$iUv-v{Z&(_DQ ze!MriJ+W=e)}6^M+vA(OYAI3miwTfD_uNCeukP}Ky6fRh5=|q?YTFV87~xbupupTi3E3s zoADFHLV0{5F;*TomZ@4bn;N6@c`92QS2SAt4#l@6w{OE>Yu^^SBT9I6b<#p`k?|LK z+fXw8WE{!(3&v64xkx-7e-RojNa82ILmBpFS4YSC@Zhl>pI5FmDTHOPuqXF_#x_ z5J%c+kB6UF?YH?e^L*5P4!=eB)y53y>&d$`%iJ&jn8+WY{NUNtoYAJ zaE{Yv{5$Iqrwy;`mG{Vg{?wkrSM1Nu+dI3^{x&>K zdhN!iGmQR`@o>(H^DyGHd0vk1NSvm9ms5ssoB79i!ip2O;(up8jy-QUFQPp%Zu9f@ z`n_l~PdYDKK`nFVwGEauUv#cmzn{OvJnqx^SA5>cDmm|2_VTvS~Z0N83C~P>zzVHZJf}*zq^n6-Xrd4S$!md%gGAurE2x@ z(a~g9&3_

m@f!p9pGdV-6n^aus*1Sjl)rH&?GzYpyqr=2S{Yi+d*vK`z}WT01AY7V4uHj8#~s|m4tsVDgTl8CaUI(CV1M5}_rcw}4-JmEBYpk* z1`&|zz3~T#iRY}qu^Q*N&rQ9UA(BV+wkpq{G7V9dhZ!B5&Cs5YCmh|)7y4$95zs3YvZ$?s7`P;L;G9?YR5DYmsU!wL2@e*H^fTjQ@bk)J7&I&v%A*x2dznnt zKPD2ktiF_S=Tc;M>wWvsMf$;>_iw>|aN0x*_KUrc!&VJ=k9DH`;98tp-(wk55GC19 z3aU*Y+xe66-N?L72KCR90&y7C8xW{2i6Ql`0hh3Nu3z@2f;clZCrqtDy3aa?vwt{k zw1SHEX;L?-*iK_V{P|ojyzF-cRUAIleyLa54@y16Ix0*3+}>b+d>T5te(|UK|1vVg zrqpjh_RoU&wqpFvzB1Tn>;0Y&owSSh>%qAtZ{qQK#sWad&$)1wjFO^@n9lq^1C+Qbr$yes{W-GOt{W{J=u@0H%*I+!* m{7ZXodv1m(>CS_u6ly(h+wJXw%_9DHjTwI@ZZNn8{{I6oPIj39 literal 0 HcmV?d00001 -- 2.30.2