Skip to content

Commit aa16cb9

Browse files
committed
Switch to a Ghidra fork instead of hacky patches
1 parent 69b7eb8 commit aa16cb9

15 files changed

+721
-447
lines changed

CMakeLists.txt

Lines changed: 26 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -90,25 +90,41 @@ find_package(glog CONFIG REQUIRED)
9090
set(GFLAGS_USE_TARGET_NAMESPACE ON)
9191
find_package(gflags CONFIG REQUIRED)
9292

93-
set(sleigh_ENABLE_TESTS OFF)
93+
# Sleigh
94+
set(sleigh_ENABLE_TESTS OFF CACHE BOOL "" FORCE)
9495
set(sleigh_RELEASE_TYPE "HEAD" CACHE STRING "" FORCE)
96+
set(sleigh_BUILD_SUPPORT ON CACHE BOOL "" FORCE)
97+
set(sleigh_BUILD_SLEIGHSPECS ON CACHE BOOL "" FORCE)
9598

96-
file(GLOB sleigh_patches "${CMAKE_CURRENT_SOURCE_DIR}/patches/sleigh/*.patch")
99+
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-register")
97100

98-
set(sleigh_ADDITIONAL_PATCHES "${sleigh_patches}" CACHE STRING "" FORCE)
101+
# Verbose fetch content updates
102+
set(FETCHCONTENT_QUIET OFF)
103+
104+
# Ghidra fork with the right patches pre-applied
105+
# This version of sleigh (HEAD) pins Ghidra somewhere between Ghidra v10.2.3 and v10.3
106+
# https://github.com/lifting-bits/sleigh/blob/7c6b742/src/setup-ghidra-source.cmake#L55-L66
107+
# This fork contains both the patches from sleigh as well as additional patches for the semantics
108+
FetchContent_Declare(GhidraSource
109+
GIT_REPOSITORY https://github.com/LLVMParty/ghidra
110+
GIT_TAG remill-sleigh-7c6b742
111+
GIT_PROGRESS TRUE
112+
GIT_SHALLOW FALSE
113+
)
114+
FetchContent_MakeAvailable(GhidraSource)
99115

100-
# GHIDRA SLEIGH
101116
FetchContent_Declare(sleigh
102117
GIT_REPOSITORY https://github.com/lifting-bits/sleigh.git
103118
GIT_TAG 7c6b742
104119
)
105-
106-
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-register")
107-
108-
set(sleigh_BUILD_SUPPORT ON CACHE BOOL "" FORCE)
109-
set(sleigh_BUILD_SLEIGHSPECS ON CACHE BOOL "" FORCE)
110120
FetchContent_MakeAvailable(sleigh)
111121

122+
# Get the Ghidra source directory from FetchContent's internal tracking
123+
FetchContent_GetProperties(GhidraSource)
124+
if(NOT ghidrasource_POPULATED)
125+
message(FATAL_ERROR "Expected sleigh to populate GhidraSource")
126+
endif()
127+
112128
# For Linux builds, group LLVM libraries into a single group
113129
# that avoids frustrating library ordering issues.
114130
if(UNIX AND NOT APPLE)
@@ -222,24 +238,6 @@ target_compile_definitions(remill_settings INTERFACE
222238
"REMILL_BUILD_SEMANTICS_DIR_PPC64_32ADDR=\"${REMILL_BUILD_SEMANTICS_DIR_PPC64_32ADDR}\""
223239
)
224240

225-
set(ghidra_patch_user "github-actions[bot]")
226-
set(ghidra_patch_email "41898282+github-actions[bot]@users.noreply.github.com")
227-
228-
# pinned stable patches list
229-
set(ghidra_patches
230-
PATCH_COMMAND "${GIT_EXECUTABLE}" config user.name "${ghidra_patch_user}" &&
231-
"${GIT_EXECUTABLE}" config user.email "${ghidra_patch_email}" &&
232-
"${GIT_EXECUTABLE}" am --ignore-space-change --ignore-whitespace --no-gpg-sign)
233-
list(APPEND ghidra_patches ${sleigh_ADDITIONAL_PATCHES})
234-
235-
FetchContent_Declare(ghidra-fork
236-
GIT_REPOSITORY https://github.com/trail-of-forks/ghidra.git
237-
GIT_TAG e7196d8
238-
${ghidra_patches}
239-
)
240-
241-
FetchContent_MakeAvailable(ghidra-fork)
242-
243241
if(SLEIGH_EXECUTABLE)
244242
set(sleigh_compiler "${SLEIGH_EXECUTABLE}")
245243
else()
@@ -249,7 +247,7 @@ endif()
249247
sleigh_compile(
250248
TARGET ppc_e200_spec
251249
COMPILER "${sleigh_compiler}"
252-
SLASPEC "${ghidra-fork_SOURCE_DIR}/Ghidra/Processors/PowerPC/data/languages/ppc_32_e200_be.slaspec"
250+
SLASPEC "${ghidrasource_SOURCE_DIR}/Ghidra/Processors/PowerPC/data/languages/ppc_32_e200_be.slaspec"
253251
LOG_FILE "${sleigh_BINARY_DIR}/sleighspecs/spec_build_logs/ppc_32_e200_be.sla.log"
254252
OUT_FILE "${sleigh_BINARY_DIR}/specfiles/Ghidra/Processors/PowerPC/data/languages/ppc_32_e200_be.sla"
255253
)

patches/README.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# Sleigh patches
2+
3+
The [sleigh](https://github.com/lifting-bits/sleigh) repository uses `git am` to apply a list of patches to a specific Ghidra base commit. These patches are mostly to make Ghidra's decompiler source code reusable as a library and suitable for packaging. You can find more information in [sleigh/src/README.md](https://github.com/lifting-bits/sleigh/blob/master/src/README.md).
4+
5+
Remill has a bunch of additional patches, which improve the semantics themselves (sleigh files). These are applied on top of the sleigh patches and specified in `sleigh_ADDITIONAL_PATCHES`.
6+
7+
To update the patches or the sleigh base commit, we need to get a cloned Ghidra source tree that only has the sleigh patches applied. From there we will apply the patches in this repository manually and recreate the patch folder.
8+
9+
1. Go in `build/_deps/ghidrasource-src` and run `git status` to make sure you are in a clean state. You might need to run `git am --abort` to abort the patching process if you had patch failures.
10+
2. Modify remill's `CMakeLists.txt` to set `sleigh_ADDITIONAL_PATCHES` to be empty and re-configure remill. This will apply just the patches of the sleigh project's tag we pinned.
11+
3. Get the commit hash of the clean Ghidra patches with `git rev-parse HEAD` and note it as `<base-commit>`.
12+
4. Apply the patches in `patches/sleigh/` one by one with `git am ../../../patches/sleigh/0001-xyz.patch`. If you get any errors, manually apply the patch (you can try `git apply ../../../patches/sleigh/0001-xyz.patch`) and then `git add .` followed by `git am --continue`. The goal is to create a commit for every patch.
13+
5. Delete all the old patches: `rm patches/sleigh/*.patch`.
14+
6. Recreate the patch list: `git format-patch remill-sleigh-7c6b742-base -o ../../../patches/sleigh/`.
15+
7. Reconfigure remill's CMake to make sure everything applies correctly and then change `sleigh_ADDITIONAL_PATCHES` batch to include all of the patches in `patches/sleigh/`.
16+
17+
**Note**: Sometimes you run into issues where `git am` cannot correctly apply all the patches. This is usually related to whitespace issues. Before exporting the patch list you can run `git rebase <base-commit> --whitespace=fix` to make sure everything is cleaned up correctly and ready to be applied.

patches/sleigh/address-warning.patch renamed to patches/sleigh/0001-Fix-narrowing-conversion-warning.patch

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
1-
From 5cef084ec56ee326d3b169c2c83950a017ae02f6 Mon Sep 17 00:00:00 2001
1+
From 622437e7f4196c92b8162913e91704792ae82b43 Mon Sep 17 00:00:00 2001
22
From: Duncan Ogilvie <[email protected]>
33
Date: Wed, 29 Oct 2025 00:52:58 +0100
4-
Subject: [PATCH] Fix narrowing conversion warning
4+
Subject: [PATCH 01/13] Fix narrowing conversion warning
55

66
error : constant expression evaluates to -1 which cannot be narrowed to type 'uintb' (aka 'unsigned long long') [-Wc++11-narrowing]
77
---
88
Ghidra/Features/Decompiler/src/decompile/cpp/address.cc | 4 ++--
99
1 file changed, 2 insertions(+), 2 deletions(-)
1010

1111
diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/address.cc b/Ghidra/Features/Decompiler/src/decompile/cpp/address.cc
12-
index 9e8039d486e..a939961c371 100644
12+
index 07bf3ba555..ffbf3efcb9 100644
1313
--- a/Ghidra/Features/Decompiler/src/decompile/cpp/address.cc
1414
+++ b/Ghidra/Features/Decompiler/src/decompile/cpp/address.cc
1515
@@ -630,8 +630,8 @@ void RangeList::decode(Decoder &decoder)
@@ -23,3 +23,6 @@ index 9e8039d486e..a939961c371 100644
2323
#endif
2424

2525
/// Treat the given \b val as a constant of \b size bytes
26+
--
27+
2.34.1
28+
Lines changed: 224 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,224 @@
1+
From f252de1b805433764a82fd63af37f580fb15a400 Mon Sep 17 00:00:00 2001
2+
From: William Tan <[email protected]>
3+
Date: Thu, 20 Apr 2023 16:24:00 -0400
4+
Subject: [PATCH 02/13] ppc e200 (#3)
5+
6+
* initial e200 sub arch
7+
8+
* fix description and gnu string
9+
10+
* fix comment
11+
---
12+
.../Processors/PowerPC/certification.manifest | 2 +
13+
.../PowerPC/data/languages/ppc.ldefs | 16 +++
14+
.../data/languages/ppc_32_e200_be.cspec | 106 ++++++++++++++++++
15+
.../data/languages/ppc_32_e200_be.slaspec | 30 +++++
16+
.../PowerPC/data/languages/ppc_common.sinc | 2 +-
17+
5 files changed, 155 insertions(+), 1 deletion(-)
18+
create mode 100644 Ghidra/Processors/PowerPC/data/languages/ppc_32_e200_be.cspec
19+
create mode 100644 Ghidra/Processors/PowerPC/data/languages/ppc_32_e200_be.slaspec
20+
21+
diff --git a/Ghidra/Processors/PowerPC/certification.manifest b/Ghidra/Processors/PowerPC/certification.manifest
22+
index ad290208f0..39c6bf1451 100644
23+
--- a/Ghidra/Processors/PowerPC/certification.manifest
24+
+++ b/Ghidra/Processors/PowerPC/certification.manifest
25+
@@ -23,6 +23,8 @@ data/languages/ppc_32_4xx_le.slaspec||GHIDRA||||END|
26+
data/languages/ppc_32_be.cspec||GHIDRA||||END|
27+
data/languages/ppc_32_be.slaspec||GHIDRA||||END|
28+
data/languages/ppc_32_be_Mac.cspec||GHIDRA||||END|
29+
+data/languages/ppc_32_e200_be.cspec||GHIDRA||||END|
30+
+data/languages/ppc_32_e200_be.slaspec||GHIDRA||||END|
31+
data/languages/ppc_32_e500_be.cspec||GHIDRA||||END|
32+
data/languages/ppc_32_e500_be.slaspec||GHIDRA||||END|
33+
data/languages/ppc_32_e500_le.cspec||GHIDRA||||END|
34+
diff --git a/Ghidra/Processors/PowerPC/data/languages/ppc.ldefs b/Ghidra/Processors/PowerPC/data/languages/ppc.ldefs
35+
index 1d3dc8e043..4b0301d7da 100644
36+
--- a/Ghidra/Processors/PowerPC/data/languages/ppc.ldefs
37+
+++ b/Ghidra/Processors/PowerPC/data/languages/ppc.ldefs
38+
@@ -174,6 +174,22 @@
39+
<external_name tool="IDA-PRO" name="ppcl"/>
40+
<external_name tool="DWARF.register.mapping.file" name="ppc.dwarf"/>
41+
</language>
42+
+ <language processor="PowerPC"
43+
+ endian="big"
44+
+ size="32"
45+
+ variant="PowerISA-e200-vle"
46+
+ version="1.5"
47+
+ slafile="ppc_32_e200_be.sla"
48+
+ processorspec="ppc_32.pspec"
49+
+ manualindexfile="../manuals/PowerPC.idx"
50+
+ id="PowerPC:BE:32:e200:VLE">
51+
+ <description>Power ISA e200 32-bit big-endian family</description>
52+
+ <truncate_space space="ram" size="4"/>
53+
+ <compiler name="default" spec="ppc_32_e200_be.cspec" id="default"/>
54+
+ <external_name tool="gnu" name="powerpc:vle"/>
55+
+ <external_name tool="IDA-PRO" name="ppc"/>
56+
+ <external_name tool="DWARF.register.mapping.file" name="ppc.dwarf"/>
57+
+ </language>
58+
<language processor="PowerPC"
59+
endian="big"
60+
size="32"
61+
diff --git a/Ghidra/Processors/PowerPC/data/languages/ppc_32_e200_be.cspec b/Ghidra/Processors/PowerPC/data/languages/ppc_32_e200_be.cspec
62+
new file mode 100644
63+
index 0000000000..cfc45d5c05
64+
--- /dev/null
65+
+++ b/Ghidra/Processors/PowerPC/data/languages/ppc_32_e200_be.cspec
66+
@@ -0,0 +1,106 @@
67+
+<?xml version="1.0" encoding="UTF-8"?>
68+
+<!-- This cspec describes the 32-bit ABI for PowerPC as it is implemented for 64-bit code.
69+
+ Presumably this ABI allows binary compatibility of 64-bit code with existing 32-bit code.
70+
+ The ABI assumes 32-bit registers and addresses, in particular the maximum sized integer value
71+
+ that can be passed in a single register is 4 bytes (even though the register is 8 bytes long).
72+
+ The cspec currently has a limited ability to model this: the maxsize attribute must still be
73+
+ set to 8 for parameter passing registers r3 - r10.
74+
+-->
75+
+<compiler_spec>
76+
+ <global>
77+
+ <range space="ram"/>
78+
+ </global>
79+
+ <data_organization>
80+
+ <pointer_size value="4"/>
81+
+ </data_organization>
82+
+ <aggressivetrim signext="true"/> <!-- Pointers are 4-bytes but are held in 8-byte registers -->
83+
+ <stackpointer register="r1" space="ram"/>
84+
+ <default_proto>
85+
+ <prototype name="__stdcall" extrapop="0" stackshift="0">
86+
+ <input pointermax="8">
87+
+ <pentry minsize="1" maxsize="4" extension="sign">
88+
+ <register name="_r3"/>
89+
+ </pentry>
90+
+ <pentry minsize="1" maxsize="4" extension="sign">
91+
+ <register name="_r4"/>
92+
+ </pentry>
93+
+ <pentry minsize="5" maxsize="8" extension="sign">
94+
+ <addr space="join" piece1="_r3" piece2="_r4"/>
95+
+ </pentry>
96+
+ <pentry minsize="1" maxsize="4" extension="sign">
97+
+ <register name="_r5"/>
98+
+ </pentry>
99+
+ <pentry minsize="1" maxsize="4" extension="sign">
100+
+ <register name="_r6"/>
101+
+ </pentry>
102+
+ <pentry minsize="5" maxsize="8" extension="sign">
103+
+ <addr space="join" piece1="_r5" piece2="_r6"/>
104+
+ </pentry>
105+
+ <pentry minsize="1" maxsize="4" extension="sign">
106+
+ <register name="_r7"/>
107+
+ </pentry>
108+
+ <pentry minsize="1" maxsize="4" extension="sign">
109+
+ <register name="_r8"/>
110+
+ </pentry>
111+
+ <pentry minsize="5" maxsize="8" extension="sign">
112+
+ <addr space="join" piece1="_r7" piece2="_r8"/>
113+
+ </pentry>
114+
+ <pentry minsize="1" maxsize="4" extension="sign">
115+
+ <register name="_r9"/>
116+
+ </pentry>
117+
+ <pentry minsize="1" maxsize="4" extension="sign">
118+
+ <register name="_r10"/>
119+
+ </pentry>
120+
+ <pentry minsize="5" maxsize="8" extension="sign">
121+
+ <addr space="join" piece1="_r9" piece2="_r10"/>
122+
+ </pentry>
123+
+ <pentry minsize="1" maxsize="500" align="4">
124+
+ <addr offset="8" space="stack"/>
125+
+ </pentry>
126+
+ </input>
127+
+ <output>
128+
+ <pentry minsize="1" maxsize="4" extension="sign">
129+
+ <register name="_r3"/>
130+
+ </pentry>
131+
+ <pentry minsize="5" maxsize="8">
132+
+ <addr space="join" piece1="_r3" piece2="_r4"/>
133+
+ </pentry>
134+
+ </output>
135+
+ <unaffected>
136+
+ <register name="r1"/> <!-- stack pointer -->
137+
+ <register name="r2"/> <!-- _SDA2_BASE_ -->
138+
+ <register name="r13"/> <!-- _SDA_BASE_ -->
139+
+ <register name="r14"/>
140+
+ <register name="r15"/>
141+
+ <register name="r16"/>
142+
+ <register name="r17"/>
143+
+ <register name="r18"/>
144+
+ <register name="r19"/>
145+
+ <register name="r20"/>
146+
+ <register name="r21"/>
147+
+ <register name="r22"/>
148+
+ <register name="r23"/>
149+
+ <register name="r24"/>
150+
+ <register name="r25"/>
151+
+ <register name="r26"/>
152+
+ <register name="r27"/>
153+
+ <register name="r28"/>
154+
+ <register name="r29"/>
155+
+ <register name="r30"/>
156+
+ <register name="r31"/>
157+
+ <register name="cr2"/>
158+
+ <register name="cr3"/>
159+
+ <register name="cr4"/>
160+
+ </unaffected>
161+
+ </prototype>
162+
+ </default_proto>
163+
+
164+
+ <callfixup name="get_pc_thunk_lr">
165+
+ <pcode>
166+
+ <body><![CDATA[
167+
+ LR = inst_dest + 4;
168+
+ ]]></body>
169+
+ </pcode>
170+
+ </callfixup>
171+
+
172+
+</compiler_spec>
173+
diff --git a/Ghidra/Processors/PowerPC/data/languages/ppc_32_e200_be.slaspec b/Ghidra/Processors/PowerPC/data/languages/ppc_32_e200_be.slaspec
174+
new file mode 100644
175+
index 0000000000..968574d198
176+
--- /dev/null
177+
+++ b/Ghidra/Processors/PowerPC/data/languages/ppc_32_e200_be.slaspec
178+
@@ -0,0 +1,30 @@
179+
+# SLA specification file for NXP PowerPC e200 series core
180+
+
181+
+# NOTE: This language variant includes some registers and instructions not supported
182+
+# by the actual processor (e.g., floating pointer registers and associated instructions).
183+
+# The actual processor only supports a subset of the registers and instructions implemented.
184+
+
185+
+@define E200
186+
+
187+
+@define ENDIAN "big"
188+
+
189+
+# Although a 32-bit architecture, 64-bit general purpose registers are supported.
190+
+# Language has been modeled using a 64-bit implementation with a 32-bit truncated
191+
+# memory space (see ldefs).
192+
+
193+
+@define REGISTER_SIZE "8"
194+
+@define BIT_64 "64"
195+
+
196+
+@define EATRUNC "ea"
197+
+
198+
+@define CTR_OFFSET "32"
199+
+
200+
+@define NoLegacyIntegerMultiplyAccumulate
201+
+
202+
+@include "ppc_common.sinc"
203+
+@include "ppc_vle.sinc"
204+
+@include "quicciii.sinc"
205+
+@include "evx.sinc"
206+
+@include "SPEF_SCR.sinc"
207+
+@include "SPE_EFSD.sinc"
208+
+@include "SPE_EFV.sinc"
209+
diff --git a/Ghidra/Processors/PowerPC/data/languages/ppc_common.sinc b/Ghidra/Processors/PowerPC/data/languages/ppc_common.sinc
210+
index aaa76cc4ac..46aa86c74c 100644
211+
--- a/Ghidra/Processors/PowerPC/data/languages/ppc_common.sinc
212+
+++ b/Ghidra/Processors/PowerPC/data/languages/ppc_common.sinc
213+
@@ -19,7 +19,7 @@ define register offset=0 size=$(REGISTER_SIZE) [
214+
r0 r1 r2 r3 r4 r5 r6 r7 r8 r9 r10 r11 r12 r13 r14 r15
215+
r16 r17 r18 r19 r20 r21 r22 r23 r24 r25 r26 r27 r28 r29 r30 r31 ];
216+
217+
-@ifdef E500
218+
+@if defined(E500) || defined(E200)
219+
# Define 4-byte general purpose sub-registers (LSB) to be used by E500 compiler specification
220+
# which must restrict parameter/return passing to low 4-bytes of the 8-byte general purpose registers.
221+
@if ENDIAN == "big"
222+
--
223+
2.34.1
224+
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
From b3bd823a17698abc4c2a906a7367018d4dedae45 Mon Sep 17 00:00:00 2001
2+
From: 2over12 <[email protected]>
3+
Date: Tue, 11 Apr 2023 13:05:24 -0400
4+
Subject: [PATCH 03/13] update target cspec
5+
6+
---
7+
Ghidra/Processors/PowerPC/data/languages/ppc_64_32.cspec | 1 +
8+
1 file changed, 1 insertion(+)
9+
10+
diff --git a/Ghidra/Processors/PowerPC/data/languages/ppc_64_32.cspec b/Ghidra/Processors/PowerPC/data/languages/ppc_64_32.cspec
11+
index 109b980e35..2160930a8a 100644
12+
--- a/Ghidra/Processors/PowerPC/data/languages/ppc_64_32.cspec
13+
+++ b/Ghidra/Processors/PowerPC/data/languages/ppc_64_32.cspec
14+
@@ -94,6 +94,7 @@
15+
</pentry>
16+
</output>
17+
<unaffected>
18+
+ <register name="r13"/>
19+
<register name="r14"/>
20+
<register name="r15"/>
21+
<register name="r16"/>
22+
--
23+
2.34.1
24+

0 commit comments

Comments
 (0)