Skip to content

Commit dd0004f

Browse files
committed
rsx: Use safe memory in RSX assembly decompiler
1 parent e59c6c3 commit dd0004f

File tree

2 files changed

+43
-29
lines changed

2 files changed

+43
-29
lines changed

rpcs3/Emu/RSX/Program/CgBinaryFragmentProgram.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -230,7 +230,7 @@ void CgBinaryDisasm::TaskFP()
230230
{
231231
m_size = 0;
232232
u32* data = reinterpret_cast<u32*>(&m_buffer[m_offset]);
233-
ensure((m_buffer_size - m_offset) % sizeof(u32) == 0);
233+
ensure((m_buffer.size() - m_offset) % sizeof(u32) == 0);
234234

235235
enum
236236
{

rpcs3/Emu/RSX/Program/CgBinaryProgram.h

Lines changed: 42 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -133,8 +133,7 @@ class CgBinaryDisasm
133133

134134
std::string m_path; // used for FP decompiler thread, delete this later
135135

136-
u8* m_buffer = nullptr;
137-
usz m_buffer_size = 0;
136+
std::vector<char> m_buffer;
138137
std::string m_arb_shader;
139138
std::string m_glsl_shader;
140139
std::string m_dst_reg_name;
@@ -196,17 +195,22 @@ class CgBinaryDisasm
196195
fs::file f(path);
197196
if (!f) return;
198197

199-
m_buffer_size = f.size();
200-
m_buffer = new u8[m_buffer_size];
201-
f.read(m_buffer, m_buffer_size);
198+
usz buffer_size = f.size();
199+
m_buffer.resize(buffer_size);
200+
f.read(m_buffer, buffer_size);
202201
fmt::append(m_arb_shader, "Loading... [%s]\n", path.c_str());
203202
}
204203

205-
~CgBinaryDisasm()
204+
template <typename T>
205+
CgBinaryDisasm(const std::span<T>& data)
206+
: m_path("<raw>")
206207
{
207-
delete[] m_buffer;
208+
m_buffer.resize(data.size_bytes());
209+
std::memcpy(m_buffer.data(), data.data(), data.size_bytes());
208210
}
209211

212+
~CgBinaryDisasm() = default;
213+
210214
static std::string GetCgParamType(u32 type)
211215
{
212216
switch (type)
@@ -226,7 +230,7 @@ class CgBinaryDisasm
226230

227231
std::string GetCgParamName(u32 offset) const
228232
{
229-
return std::string(reinterpret_cast<char*>(&m_buffer[offset]));
233+
return std::string(&m_buffer[offset]);
230234
}
231235

232236
std::string GetCgParamRes(u32 /*offset*/) const
@@ -238,7 +242,7 @@ class CgBinaryDisasm
238242

239243
std::string GetCgParamSemantic(u32 offset) const
240244
{
241-
return std::string(reinterpret_cast<char*>(&m_buffer[offset]));
245+
return std::string(&m_buffer[offset]);
242246
}
243247

244248
std::string GetCgParamValue(u32 offset, u32 end_offset) const
@@ -274,8 +278,8 @@ class CgBinaryDisasm
274278

275279
auto swap_be32 = [&](u32 start_offset, size_t size_bytes)
276280
{
277-
auto start = reinterpret_cast<u32*>(m_buffer + start_offset);
278-
auto end = reinterpret_cast<u32*>(m_buffer + start_offset + size_bytes);
281+
auto start = reinterpret_cast<u32*>(m_buffer.data() + start_offset);
282+
auto end = reinterpret_cast<u32*>(m_buffer.data() + start_offset + size_bytes);
279283

280284
for (auto data = start; data < end; ++data)
281285
{
@@ -290,7 +294,7 @@ class CgBinaryDisasm
290294
swap_be32(prog.parameterArray, sizeof(CgBinaryParameter) * prog.parameterCount);
291295

292296
// 3. Swap the ucode
293-
swap_be32(prog.ucode, m_buffer_size - prog.ucode);
297+
swap_be32(prog.ucode, m_buffer.size() - prog.ucode);
294298

295299
// 4. Swap the domain header
296300
if (be_profile == 7004u)
@@ -311,7 +315,7 @@ class CgBinaryDisasm
311315
}
312316
}
313317

314-
void BuildShaderBody()
318+
void BuildShaderBody(bool include_glsl = true)
315319
{
316320
ParamArray param_array;
317321

@@ -355,27 +359,32 @@ class CgBinaryDisasm
355359
m_offset = prog.ucode;
356360
TaskFP();
357361

362+
if (!include_glsl)
363+
{
364+
return;
365+
}
366+
358367
u32 unused;
359368
std::vector<u32> be_data;
360369

361370
// Swap bytes. FP decompiler expects input in BE
362-
for (u32* ptr = reinterpret_cast<u32*>(m_buffer + m_offset),
363-
*end = reinterpret_cast<u32*>(m_buffer + m_buffer_size);
371+
for (u32* ptr = reinterpret_cast<u32*>(m_buffer.data() + m_offset),
372+
*end = reinterpret_cast<u32*>(m_buffer.data() + m_buffer.size());
364373
ptr < end; ++ptr)
365374
{
366375
be_data.push_back(std::bit_cast<be_t<u32>>(*ptr));
367376
}
368377

369-
RSXFragmentProgram prog;
378+
RSXFragmentProgram rsx_prog;
370379
auto metadata = program_hash_util::fragment_program_utils::analyse_fragment_program(be_data.data());
371-
prog.ctrl = (fprog.outputFromH0 ? 0 : 0x40) | (fprog.depthReplace ? 0xe : 0);
372-
prog.offset = metadata.program_start_offset;
373-
prog.ucode_length = metadata.program_ucode_length;
374-
prog.total_length = metadata.program_ucode_length + metadata.program_start_offset;
375-
prog.data = reinterpret_cast<u8*>(be_data.data()) + metadata.program_start_offset;
376-
for (u32 i = 0; i < 16; ++i) prog.texture_state.set_dimension(rsx::texture_dimension_extended::texture_dimension_2d, i);
380+
rsx_prog.ctrl = (fprog.outputFromH0 ? 0 : 0x40) | (fprog.depthReplace ? 0xe : 0);
381+
rsx_prog.offset = metadata.program_start_offset;
382+
rsx_prog.ucode_length = metadata.program_ucode_length;
383+
rsx_prog.total_length = metadata.program_ucode_length + metadata.program_start_offset;
384+
rsx_prog.data = reinterpret_cast<u8*>(be_data.data()) + metadata.program_start_offset;
385+
for (u32 i = 0; i < 16; ++i) rsx_prog.texture_state.set_dimension(rsx::texture_dimension_extended::texture_dimension_2d, i);
377386
#ifndef WITHOUT_OPENGL
378-
GLFragmentDecompilerThread(m_glsl_shader, param_array, prog, unused).Task();
387+
GLFragmentDecompilerThread(m_glsl_shader, param_array, rsx_prog, unused).Task();
379388
#endif
380389
}
381390

@@ -409,18 +418,23 @@ class CgBinaryDisasm
409418

410419
m_arb_shader += "\n";
411420
m_offset = prog.ucode;
412-
ensure((m_buffer_size - m_offset) % sizeof(u32) == 0);
421+
ensure((m_buffer.size() - m_offset) % sizeof(u32) == 0);
413422

414423
u32* vdata = reinterpret_cast<u32*>(&m_buffer[m_offset]);
415424
m_data.resize(prog.ucodeSize / sizeof(u32));
416425
std::memcpy(m_data.data(), vdata, prog.ucodeSize);
417426
TaskVP();
418427

419-
RSXVertexProgram prog;
420-
program_hash_util::vertex_program_utils::analyse_vertex_program(vdata, 0, prog);
421-
for (u32 i = 0; i < 4; ++i) prog.texture_state.set_dimension(rsx::texture_dimension_extended::texture_dimension_2d, i);
428+
if (!include_glsl)
429+
{
430+
return;
431+
}
432+
433+
RSXVertexProgram rsx_prog;
434+
program_hash_util::vertex_program_utils::analyse_vertex_program(vdata, 0, rsx_prog);
435+
for (u32 i = 0; i < 4; ++i) rsx_prog.texture_state.set_dimension(rsx::texture_dimension_extended::texture_dimension_2d, i);
422436
#ifndef WITHOUT_OPENGL
423-
GLVertexDecompilerThread(prog, m_glsl_shader, param_array).Task();
437+
GLVertexDecompilerThread(rsx_prog, m_glsl_shader, param_array).Task();
424438
#endif
425439
}
426440
}

0 commit comments

Comments
 (0)