From 2fb4ab4291322a441c3a4a5c15d04b9a349d864f Mon Sep 17 00:00:00 2001 From: Ryan Scott Date: Thu, 2 Nov 2023 11:58:04 -0400 Subject: [PATCH] `macaw-base`: Resolve PPC{32,64} relocations This builds on top of the work in https://github.com/GaloisInc/elf-edit/pull/41. For now, I only add support for a select few relocation types, leaving the rest as future work. --- base/ChangeLog.md | 2 + base/src/Data/Macaw/Memory/ElfLoader.hs | 170 ++++++++++++++++++- deps/elf-edit | 2 +- macaw-ppc/tests/ppc32/Makefile | 4 + macaw-ppc/tests/ppc32/test-relocs.c | 6 + macaw-ppc/tests/ppc32/test-relocs.exe | Bin 0 -> 67116 bytes macaw-ppc/tests/ppc32/test-relocs.s | 48 ++++++ macaw-ppc/tests/ppc32/test-relocs.s.expected | 6 + macaw-ppc/tests/ppc64/Dockerfile | 10 ++ macaw-ppc/tests/ppc64/Makefile | 4 + macaw-ppc/tests/ppc64/README.md | 6 + macaw-ppc/tests/ppc64/test-relocs.c | 6 + macaw-ppc/tests/ppc64/test-relocs.exe | Bin 0 -> 67712 bytes macaw-ppc/tests/ppc64/test-relocs.s | 50 ++++++ macaw-ppc/tests/ppc64/test-relocs.s.expected | 6 + 15 files changed, 315 insertions(+), 5 deletions(-) create mode 100644 macaw-ppc/tests/ppc32/test-relocs.c create mode 100755 macaw-ppc/tests/ppc32/test-relocs.exe create mode 100644 macaw-ppc/tests/ppc32/test-relocs.s create mode 100644 macaw-ppc/tests/ppc32/test-relocs.s.expected create mode 100644 macaw-ppc/tests/ppc64/Dockerfile create mode 100644 macaw-ppc/tests/ppc64/README.md create mode 100644 macaw-ppc/tests/ppc64/test-relocs.c create mode 100755 macaw-ppc/tests/ppc64/test-relocs.exe create mode 100644 macaw-ppc/tests/ppc64/test-relocs.s create mode 100644 macaw-ppc/tests/ppc64/test-relocs.s.expected diff --git a/base/ChangeLog.md b/base/ChangeLog.md index 5edafd9d2..feb3ffb05 100644 --- a/base/ChangeLog.md +++ b/base/ChangeLog.md @@ -9,6 +9,8 @@ non–position-independent executables. These were previously omitted due to an oversight in the implementation. +- Add support for PPC32 and PPC64 relocations in `Data.Macaw.Memory.ElfLoader`. + ### API Changes - Architecture-specific block terminators can now contain macaw values diff --git a/base/src/Data/Macaw/Memory/ElfLoader.hs b/base/src/Data/Macaw/Memory/ElfLoader.hs index 3afcfff13..a5f29fe6c 100644 --- a/base/src/Data/Macaw/Memory/ElfLoader.hs +++ b/base/src/Data/Macaw/Memory/ElfLoader.hs @@ -796,6 +796,164 @@ relaTargetARM64 end msegIndex symtab rel addend relFlag = tp -> do throwError $ RelocationUnsupportedType (show tp) +-- | Attempt to resolve a PPC32-specific symbol. +relaTargetPPC32 :: Endianness + -- ^ Endianness of relocations + -> Maybe SegmentIndex + -- ^ Index of segment for dynamic relocations + -> SymbolTable 32 -- ^ Symbol table + -> Elf.RelEntry Elf.PPC32_RelocationType -- ^ Relocation entry + -> MemWord 32 + -- ^ Addend of symbol + -> RelFlag + -> SymbolResolver (Relocation 32) +relaTargetPPC32 end msegIndex symtab rel addend _relFlag = + case Elf.relType rel of + Elf.R_PPC_ADDR32 -> do + sym <- resolveRelocationSym symtab (Elf.relSym rel) + pure $! Relocation { relocationSym = sym + , relocationOffset = addend + , relocationIsRel = False + , relocationSize = 4 + , relocationIsSigned = False + , relocationEndianness = end + , relocationJumpSlot = False + } + Elf.R_PPC_GLOB_DAT -> do + sym <- resolveRelocationSym symtab (Elf.relSym rel) + pure $! Relocation { relocationSym = sym + , relocationOffset = addend + , relocationIsRel = False + , relocationSize = 4 + , relocationIsSigned = False + , relocationEndianness = end + , relocationJumpSlot = False + } + Elf.R_PPC_RELATIVE -> do + -- This relocation has the value B + A where + -- - A is the addend for the relocation, and + -- - B resolves to the difference between the + -- address at which the segment defining the symbol was + -- loaded and the address at which it was linked. + -- + -- Since the address at which it was linked is a constant, we + -- create a non-relative address but subtract the link address + -- from the offset. + + -- Get the address at which it was linked so we can subtract from offset. + let linktimeAddr = Elf.relAddr rel + + -- Resolve the symbol using the index in the relocation. + sym <- + if Elf.relSym rel == 0 then do + case msegIndex of + Nothing -> do + throwError $ RelocationZeroSymbol + Just idx -> + pure $! SegmentBaseAddr idx + else do + resolveRelocationSym symtab (Elf.relSym rel) + pure $! Relocation { relocationSym = sym + , relocationOffset = addend - fromIntegral linktimeAddr + , relocationIsRel = False + , relocationSize = 4 + , relocationIsSigned = False + , relocationEndianness = end + , relocationJumpSlot = False + } + Elf.R_PPC_JMP_SLOT -> do + -- This is a PLT relocation + sym <- resolveRelocationSym symtab (Elf.relSym rel) + pure $! Relocation { relocationSym = sym + , relocationOffset = addend + , relocationIsRel = False + , relocationSize = 4 + , relocationIsSigned = False + , relocationEndianness = end + , relocationJumpSlot = True + } + tp -> + throwError $ RelocationUnsupportedType (show tp) + +-- | Attempt to resolve a PPC64-specific symbol. +relaTargetPPC64 :: Endianness + -- ^ Endianness of relocations + -> Maybe SegmentIndex + -- ^ Index of segment for dynamic relocations + -> SymbolTable 64 -- ^ Symbol table + -> Elf.RelEntry Elf.PPC64_RelocationType -- ^ Relocation entry + -> MemWord 64 + -- ^ Addend of symbol + -> RelFlag + -> SymbolResolver (Relocation 64) +relaTargetPPC64 end msegIndex symtab rel addend _relFlag = + case Elf.relType rel of + Elf.R_PPC64_ADDR64 -> do + sym <- resolveRelocationSym symtab (Elf.relSym rel) + pure $! Relocation { relocationSym = sym + , relocationOffset = addend + , relocationIsRel = False + , relocationSize = 8 + , relocationIsSigned = False + , relocationEndianness = end + , relocationJumpSlot = False + } + Elf.R_PPC64_GLOB_DAT -> do + sym <- resolveRelocationSym symtab (Elf.relSym rel) + pure $! Relocation { relocationSym = sym + , relocationOffset = addend + , relocationIsRel = False + , relocationSize = 8 + , relocationIsSigned = False + , relocationEndianness = end + , relocationJumpSlot = False + } + Elf.R_PPC64_RELATIVE -> do + -- This relocation has the value B + A where + -- - A is the addend for the relocation, and + -- - B resolves to the difference between the + -- address at which the segment defining the symbol was + -- loaded and the address at which it was linked. + -- + -- Since the address at which it was linked is a constant, we + -- create a non-relative address but subtract the link address + -- from the offset. + + -- Get the address at which it was linked so we can subtract from offset. + let linktimeAddr = Elf.relAddr rel + + -- Resolve the symbol using the index in the relocation. + sym <- + if Elf.relSym rel == 0 then do + case msegIndex of + Nothing -> do + throwError $ RelocationZeroSymbol + Just idx -> + pure $! SegmentBaseAddr idx + else do + resolveRelocationSym symtab (Elf.relSym rel) + pure $! Relocation { relocationSym = sym + , relocationOffset = addend - fromIntegral linktimeAddr + , relocationIsRel = False + , relocationSize = 8 + , relocationIsSigned = False + , relocationEndianness = end + , relocationJumpSlot = False + } + Elf.R_PPC64_JMP_SLOT -> do + -- This is a PLT relocation + sym <- resolveRelocationSym symtab (Elf.relSym rel) + pure $! Relocation { relocationSym = sym + , relocationOffset = addend + , relocationIsRel = False + , relocationSize = 8 + , relocationIsSigned = False + , relocationEndianness = end + , relocationJumpSlot = True + } + tp -> + throwError $ RelocationUnsupportedType (show tp) + toEndianness :: Elf.ElfData -> Endianness toEndianness Elf.ELFDATA2LSB = LittleEndian toEndianness Elf.ELFDATA2MSB = BigEndian @@ -809,13 +967,17 @@ getRelocationResolver hdr = case (Elf.headerClass hdr, Elf.headerMachine hdr) of (Elf.ELFCLASS64, Elf.EM_X86_64) -> pure $ SomeRelocationResolver relaTargetX86_64 - (Elf.ELFCLASS32, Elf.EM_ARM) -> do - let end = toEndianness (Elf.headerData hdr) + (Elf.ELFCLASS32, Elf.EM_ARM) -> pure $ SomeRelocationResolver $ relaTargetARM32 end - (Elf.ELFCLASS64, Elf.EM_AARCH64) -> do - let end = toEndianness (Elf.headerData hdr) + (Elf.ELFCLASS64, Elf.EM_AARCH64) -> pure $ SomeRelocationResolver $ relaTargetARM64 end + (Elf.ELFCLASS32, Elf.EM_PPC) -> + pure $ SomeRelocationResolver $ relaTargetPPC32 end + (Elf.ELFCLASS64, Elf.EM_PPC64) -> + pure $ SomeRelocationResolver $ relaTargetPPC64 end (_,mach) -> throwError $ UnsupportedArchitecture (show mach) + where + end = toEndianness (Elf.headerData hdr) resolveRela :: ( MemWidth w , Elf.RelocationWidth tp ~ w diff --git a/deps/elf-edit b/deps/elf-edit index 3ba7d7148..5531161f6 160000 --- a/deps/elf-edit +++ b/deps/elf-edit @@ -1 +1 @@ -Subproject commit 3ba7d7148adc6029b0046229c4fecbb9ee048f9b +Subproject commit 5531161f64f92e13ae04cfe0de0042754ae050cd diff --git a/macaw-ppc/tests/ppc32/Makefile b/macaw-ppc/tests/ppc32/Makefile index fabefde1a..5a4651509 100644 --- a/macaw-ppc/tests/ppc32/Makefile +++ b/macaw-ppc/tests/ppc32/Makefile @@ -7,6 +7,10 @@ all: $(patsubst %c,%exe,$(wildcard *.c)) %.s: %.c $(CC) -fno-stack-protector -S -c $< -o $@ +# This test relies on the binary having dynamic relocations. +test-relocs.exe: test-relocs.s + $(CC) -fno-stack-protector -nostartfiles $< -o $@ + .PRECIOUS: %.s clean: diff --git a/macaw-ppc/tests/ppc32/test-relocs.c b/macaw-ppc/tests/ppc32/test-relocs.c new file mode 100644 index 000000000..aba653d40 --- /dev/null +++ b/macaw-ppc/tests/ppc32/test-relocs.c @@ -0,0 +1,6 @@ +#include + +int main(void) { + printf("Hello, %s!\n", "World"); + return 0; +} diff --git a/macaw-ppc/tests/ppc32/test-relocs.exe b/macaw-ppc/tests/ppc32/test-relocs.exe new file mode 100755 index 0000000000000000000000000000000000000000..2ed42f008634c4bde9e61fd2dcd51a9ff9fd0d0e GIT binary patch literal 67116 zcmeIyPi$0G6vy%VW(rc;%78^lKpg@m5M}sdLqKipwDb>gDE}j3%wyUa?4;9~Ix{6; zN+{|=6JvxRJz-%Pxp+T)1;%LS2}UxWPn?3+?zjciz)dA<_N!rlC0w_TgOp38)c3d`+3DwcT-vp}9h!Ya`D&X}fe)3ZTjAO?Zjn@e zDiwwDt|)BIHuD?W1{Nyc(+an$HDmvqJ*l7-D)=^v)zN%n#r%TiE$q6YYX}P3--pJw zN8#rRjUSIWm$;?h=tFZ`qKM~@E5Bc}^;0_k#ESjD(YS@3AM7rd#&(wrnR+#|SGhGC zH`nCw=xNv1KD2b`>#;4L-+BCrq3_anj(>1_PIIw~w^9C}))7x^umkNiZaeLF)3s8i zao!E*4)+g)`!YQ?o6xH9x}LhLRI=-kpYx}u?8pTh?Z35;w>Iz2u1U;a3taa{Ke*1> z7dtNYrc>^~dx@LAFD1UreYN+k5$ARuOgndZ+e;S@UU8|p4%arjCOQB1Pt89r=U=@z zI_J{ov|jJIRO0HS>PpG^(YdyC?_4U;J9*d5bvA!LIQi$b+4ki8Y{%K|tMBW)b7#A) z#?E_Cyj-o73z{D(mdn*=(ofa5u64oYaVLmqwv2wc=LoVFdJ;{ z^t{_OzDYG^k#pIHQv>U>S3U`{T~FpZJ6!g5S9BBX+&0^D!LU9DIQC?gqzkuDro*q+M_2vLHkS(4-7n)-f?^;Kx=Z;G!+$96qWNB7zmvi-6O-!`$ST^vEJBKE0(L{^~|^n54|#)J#u)!h2ik%>2Po)96FIbG8m2=I^n|M z+|mAQE<8FkbaL=icq-eU8w}latyF28@9P`R9qu0p_houqSS;ild3BY7mKm$p!+IlM zYq+U=sp4Fwerc+aA5-6`wfc$pNDCEf(=Jn~Hj0_oD>Ip~nNqp1t5k44o5n1NiST?aKUEAT3aW}Tzh-`_ zG_G~3svfUSO%*GR7W#kuzgcy5{{?LCfPWACGZdX~bJn&g?Af(C-7o)sY`2N1`TMKm z{d$*wQ*U*8XZ(A!NqIbPy+xnGo*k>Zp*n?2EA0KTJ*~#>`G`V~sjpkml)`_H)cF=) z-?8XhV(aPM^Y5RnVPVbQ0E^dDw`9kvTU4FmU;Apvl@)ewzn(pH7XJHXWA+YNZ|~j( zg + +int main(void) { + printf("Hello, %s!\n", "World"); + return 0; +} diff --git a/macaw-ppc/tests/ppc64/test-relocs.exe b/macaw-ppc/tests/ppc64/test-relocs.exe new file mode 100755 index 0000000000000000000000000000000000000000..10238a21e89d6376cd15358ec1b1864b634b653d GIT binary patch literal 67712 zcmeIzPiP!f90%|>vuRBKI;{-`QgCZ4wrHoD5<;rQW|O8#NE$*&@ejy!H@j_?Zg%7D zq@*Qj(-JV^O+3UuPz4P|3Lfmii{P=x-o4a=u*FLilz=wl@Au~YraRjNMG!oE2WEfs ze)E2B-h5{E&9(lK)3$A?XtPx-9qWW+t=CMxM@K8c(NaCCTeZ+{tJ+KLX4;!*=dFi- zoQ6mx-*f(Pq-v!Sw3|AcPf}exQfjw8@i_9lc;903I?(lEk%nyxGbZZ0(RDmm+8(X& zuVcj{4L!qorEGmZRM3<9ySlNk&N5NoAK#nYA3O2=#UiB+a-KGcO*#K39>dfnZu3b; z#UrKmah^7bTsKZ_Qy0H4xzD=$o6^;kI9e=ZyE=~+b6uTowd{77JdeY3O$>~lRjti0 z9>3R?_~eIye0%e+-+Y|;{KJpvoIHzA*A)JPuzk-)ooF7DJcBMZQz?}E^J-vZsJG8M z=5}&#o319;b2zcHP~iFT3lk0J*ovP!_v3e1Z)<6F=)sNaZ42)uR%^Z2lcS4GNpnhv z`4)S1%~H-EKL%@S`-AKAC%4a?xDl*(FDd#a+x~ODKYmw%8PLE7K)}Jd2%l2yTO|@lV%3iGv2M-sP6RQi^xAs1GU#Z%# zYT*Y!@M{zJ;ES6tRzEIu2Op-$~uw05Vj-n7y?pBoAb zDUS^T5P$##AOHafKmY;|fB*y_009U<00Izz00bZa0SG_<0uX=z1Rwwb2tWV=5P$## zAOHafKmY;|fB*y_009U<00Izz00bZa0SG_<0uX=z1Rwwb2tWV=5P$##AOHafKmY;| zfB*y_009U<00Izz00bZa0SG_<0uX=z1Rwwb2tWV=5P$##AOHafKmY;|fB*y_009U< z00Izz00bZa0SG_<0uX=z1Rwwb2tWV=5P$##AOHafKmY;|fB*y_009U<00Izz00bZa z0SG_<0uX=z1Rwwb2tWV=5P$##AOHafKmY;|fB*y_009U<00Izz00bZa0SG_<0uX=z z1Rwwb2tWV=5P$##AOHafKmY;|fB*y_009U<00Izz00bZa0SG_<0uX=z1Rwwb2tWV= z5P$##AOHafKmY;|fB*y_009U<00Izz00bZaf&Zs~Wu~QLIavRV+m5okO@51MFPnC= zX}@9G+f3YN;&v0;Ol&n#LV^z*TbfFar2k%X<|z}OtWlz zW!eEp+RXg~54l10UvT`dH=38egkxWeU5eWSeSNPa51q}SgWHsE9Dk?ITaOyY z*%jv3YaC^x>psoLjwP>8c!u(h&c~T~p1Z>yv0tl61;4~Hrm;z$uW1|-=S)`)&(p)* zX#OwJxs4oNqx?pmV|#eCC$}u!l-yUU?sQ?3d{uX@>u3&3oAkdz*KKs3P=3DZAF1Sv z<;ki$sXXsOu~53`jg3rH^3`(jQeJtd-W*Mz8S0~R1EXiX{z32bc=}AgH+X7XrS#U( z?amZ^Z!%LXx-*qR$v@xIGcYpL+vgo~JC&EuW&8|xj(HI=DODK~eyL?eXJuY_kVMW&r<^m;*2)(108^kO%@&(fd!9iUy-W2ramOSH}$Gy_V|>xyY~(K`LRIhJ~} z4n^w`e?RJL^txecdML_wMe5CZ6|GzR9`l+d^OpKH$_>&^e_6dr{jzDAsO0-)x<%t~ zdyM8U3xm{~^)LFa@Z9U?ulrGs*VAZS z<@@A5@>gx)ezbA^67Aw5>-T-i(PrP*L8&_?N=V89#d+GL-rT>e&k|Madqe%@`aI0i z2K8ngkJj@>f4N_-|6qgqyL^HktBGnXY)8NK^`BB!-!~U<4=4IA$oIkGdi~Ag^R&tQ z+4D=<<^D~*d_N>=XReb?>bdT9&c8!R885uPyj?1ge99C`kUT&C zuW6S78~R1{ho#U&>Cch(=!)@vL3h};?@@e)cD^2O_1EWbll=em$>_(jrQfwE7aqv< Uxy5VKX7%re-PN}yN{H(J0!brgIsgCw literal 0 HcmV?d00001 diff --git a/macaw-ppc/tests/ppc64/test-relocs.s b/macaw-ppc/tests/ppc64/test-relocs.s new file mode 100644 index 000000000..409792b7f --- /dev/null +++ b/macaw-ppc/tests/ppc64/test-relocs.s @@ -0,0 +1,50 @@ + .file "test-relocs.c" + .section ".text" + .section .rodata + .align 3 +.LC0: + .string "World" + .align 3 +.LC1: + .string "Hello, %s!\n" + .section ".text" + .align 2 + .globl main + .section ".opd","aw" + .align 3 +main: + .quad .L.main,.TOC.@tocbase,0 + .previous + .type main, @function +.L.main: +.LFB0: + .cfi_startproc + mflr 0 + std 0,16(1) + std 31,-8(1) + stdu 1,-128(1) + .cfi_def_cfa_offset 128 + .cfi_offset 65, 16 + .cfi_offset 31, -8 + mr 31,1 + .cfi_def_cfa_register 31 + addis 4,2,.LC0@toc@ha + addi 4,4,.LC0@toc@l + addis 3,2,.LC1@toc@ha + addi 3,3,.LC1@toc@l + bl printf + nop + li 9,0 + mr 3,9 + addi 1,31,128 + .cfi_def_cfa 1, 0 + ld 0,16(1) + mtlr 0 + ld 31,-8(1) + blr + .long 0 + .byte 0,0,0,1,128,1,0,1 + .cfi_endproc +.LFE0: + .size main,.-.L.main + .ident "GCC: (Ubuntu 9.4.0-1ubuntu1~20.04) 9.4.0" diff --git a/macaw-ppc/tests/ppc64/test-relocs.s.expected b/macaw-ppc/tests/ppc64/test-relocs.s.expected new file mode 100644 index 000000000..a1be68331 --- /dev/null +++ b/macaw-ppc/tests/ppc64/test-relocs.s.expected @@ -0,0 +1,6 @@ +R { funcs = [(0x10000300, [ (0x10000300, 40) + , (0x10000328, 32) + ]) + ] + , ignoreBlocks = [0x100002e0] + }