@@ -23,87 +23,71 @@ bool exclude_unneeded_sections = true;
23
23
24
24
std::string DoNameGen (const std::string& libName, int id, int version); // namegen.cpp
25
25
26
- void label_regsaveloads ( ea_t start, ea_t end)
26
+ struct saverest_pattern
27
27
{
28
- // "std %r14, -0x98(%sp)" followed by "std %r15, -0x90(%sp)"
29
- uint8 save_pattern[] = {
30
- 0xF9 , 0xC1 , 0xFF , 0x68 , 0xF9 , 0xE1 , 0xFF , 0x70
31
- };
32
- // "ld %r14, -0x98(%sp)" followed by "ld %r15, -0x90(%sp)"
33
- uint8 load_pattern[] = {
34
- 0xE9 , 0xC1 , 0xFF , 0x68 , 0xE9 , 0xE1 , 0xFF , 0x70
35
- };
36
- // "stfd %f14, -0x90(%r12)" followed by "stfd %f15, -0x88(%r12)"
37
- uint8 savef_pattern[] = {
38
- 0xD9 , 0xCC , 0xFF , 0x70 , 0xD9 , 0xEC , 0xFF , 0x78
39
- };
40
- // "lfd %f14, -0x90(%r12)" followed by "lfd %f15, -0x88(%r12)"
41
- uint8 loadf_pattern[] = {
42
- 0xC9 , 0xCC , 0xFF , 0x70 , 0xC9 , 0xEC , 0xFF , 0x78
43
- };
44
-
45
-
46
- uint8* patterns[] = {
47
- save_pattern,
48
- load_pattern,
49
- savef_pattern,
50
- loadf_pattern
51
- };
52
- const char * pattern_labels[] = {
53
- " __savegprlr_%d" ,
54
- " __restgprlr_%d" ,
55
- " __savefpr_%d" ,
56
- " __restfpr_%d"
57
- };
28
+ const char * name;
29
+ const std::vector<uint8_t > pattern;
30
+ bool is_prolog;
31
+ int start_reg;
32
+ int end_reg;
33
+ int fn_size;
34
+ int final_size;
35
+ };
58
36
59
- init_ignore_micro ();
37
+ std::list<saverest_pattern> patterns =
38
+ {
39
+ { " __savegprlr_%d" , {0xF9 , 0xC1 , 0xFF , 0x68 , 0xF9 , 0xE1 , 0xFF , 0x70 }, true , 14 , 32 , 4 , 12 },
40
+ { " __restgprlr_%d" , {0xE9 , 0xC1 , 0xFF , 0x68 , 0xE9 , 0xE1 , 0xFF , 0x70 }, false , 14 , 32 , 4 , 16 },
60
41
61
- for (int pat_idx = 0 ; pat_idx < 4 ; pat_idx++)
42
+ { " __savefpr_%d" , {0xD9 , 0xCC , 0xFF , 0x70 , 0xD9 , 0xEC , 0xFF , 0x78 }, true , 14 , 32 , 4 , 8 },
43
+ { " __restfpr_%d" , {0xC9 , 0xCC , 0xFF , 0x70 , 0xC9 , 0xEC , 0xFF , 0x78 }, false , 14 , 32 , 4 , 8 },
44
+
45
+ { " __savevmx_%d" , {0x39 , 0x60 , 0xFE , 0xE0 , 0x7D , 0xCB , 0x61 , 0xCE }, true , 14 , 32 , 8 , 12 },
46
+ { " __restvmx_%d" , {0x39 , 0x60 , 0xFE , 0xE0 , 0x7D , 0xCB , 0x60 , 0xCE }, false , 14 , 32 , 8 , 12 },
47
+
48
+ // vmx128, same name as above
49
+ { " __savevmx_%d" , {0x39 , 0x60 , 0xFC , 0x00 , 0x10 , 0x0B , 0x61 , 0xCB }, true , 64 , 128 , 8 , 12 },
50
+ { " __restvmx_%d" , {0x39 , 0x60 , 0xFC , 0x00 , 0x10 , 0x0B , 0x60 , 0xCB }, false , 64 , 128 , 8 , 12 },
51
+ };
52
+
53
+ void label_regsaveloads (ea_t start, ea_t end)
54
+ {
55
+ for (auto & pattern : patterns)
62
56
{
63
57
ea_t addr = start;
64
58
65
59
while (addr != BADADDR)
66
60
{
67
- addr = bin_search (addr, end, patterns[pat_idx] , NULL , 8 , BIN_SEARCH_CASE | BIN_SEARCH_FORWARD);
61
+ addr = bin_search (addr, end, pattern. pattern . data () , NULL , 8 , BIN_SEARCH_CASE | BIN_SEARCH_FORWARD);
68
62
if (addr == BADADDR)
69
63
break ;
70
64
71
- for (int i = 14 ; i < 32 ; i++)
65
+ for (int i = pattern. start_reg ; i < pattern. end_reg ; i++)
72
66
{
73
- int size = 4 ;
74
-
75
- // final one is 0xC bytes when saving, 0x10 when loading
76
- // (final fpr pattern is 0x8 when saving/loading)
77
- if (i == 31 )
78
- {
79
- size = (pat_idx == 0 ) ? 0xC : 0x10 ;
80
- if (pat_idx > 1 ) size = 8 ;
81
- }
67
+ int size = pattern.fn_size ;
68
+ if (i + 1 == pattern.end_reg )
69
+ size = pattern.final_size ;
82
70
83
71
// reset addr
84
72
del_items (addr, 0 , 8 );
85
73
create_insn (addr);
86
74
87
- set_name (addr, qstring ().sprnt (pattern_labels[pat_idx] , i).c_str (), SN_FORCE);
75
+ set_name (addr, qstring ().sprnt (pattern. name , i).c_str (), SN_FORCE);
88
76
89
77
func_t fn (addr, addr + size);
90
78
fn.flags |= FUNC_OUTLINE | FUNC_HIDDEN;
91
79
add_func_ex (&fn);
92
80
93
81
// Mark save/rest functions as prolog/epilog to hide them from decompiler
94
82
int hide_size = size;
95
- if (i == 31 )
96
- hide_size -= 4 ; // don't hide last blr
83
+ if (i + 1 == pattern. end_reg )
84
+ hide_size -= 4 ; // don't hide last blr
97
85
for (int insn = 0 ; insn < hide_size; insn += 4 )
98
86
{
99
- if (pat_idx == 0 || pat_idx == 2 )
100
- {
101
- mark_prolog_insn (addr + insn);
102
- }
103
- else
104
- {
105
- mark_epilog_insn (addr + insn);
106
- }
87
+ if (pattern.is_prolog )
88
+ mark_prolog_insn (addr + insn);
89
+ else
90
+ mark_epilog_insn (addr + insn);
107
91
}
108
92
109
93
addr += size;
@@ -114,6 +98,8 @@ void label_regsaveloads(ea_t start, ea_t end)
114
98
115
99
void pe_add_sections (XEXFile& file)
116
100
{
101
+ init_ignore_micro ();
102
+
117
103
for (const auto & section : file.sections ())
118
104
{
119
105
// New buffer for section name so we can null-terminate it
@@ -206,21 +192,37 @@ void pe_add_sections(XEXFile& file)
206
192
if (sec_addr + sec_size > file.image_size ())
207
193
sec_size = file.image_size () - sec_addr;
208
194
209
- // Store function addrs from .pdata inside a std::vector, so we can iterate over them in reverse
210
- std::vector<uint32_t > funcs;
195
+ struct RUNTIME_FUNCTION_INFO // bitfield portion of RUNTIME_FUNCTION
196
+ {
197
+ uint32_t PrologLength : 8 ;
198
+ uint32_t FunctionLength : 22 ;
199
+ uint32_t FunctionType : 2 ;
200
+
201
+ inline xex::RuntimeFunctionType RuntimeFunctionType () {
202
+ return (xex::RuntimeFunctionType)FunctionType;
203
+ }
204
+ };
205
+
206
+ // Read function addrs from .pdata into vector so we can get a count before asking IDA to create functions for them
207
+ std::unordered_map<uint32_t , RUNTIME_FUNCTION_INFO> funcs;
211
208
int offset = 0 ;
212
209
while (offset < sec_size)
213
210
{
214
211
create_data (seg_addr + offset, dword_flag (), 4 , BADNODE);
215
212
create_data (seg_addr + offset + 4 , dword_flag (), 4 , BADNODE);
216
213
217
214
auto * fn_ptr = reinterpret_cast <const xe::be<uint32_t >*>(file.pe_data () + sec_addr + offset);
218
- ea_t fn = * fn_ptr;
215
+ uint32_t fn_ea = fn_ptr[ 0 ] ;
219
216
220
- funcs.push_back (fn);
217
+ if (fn_ea)
218
+ {
219
+ uint32_t fn_info_raw = fn_ptr[1 ]; // endian-swap the field for us
220
+ RUNTIME_FUNCTION_INFO fn_info = *(RUNTIME_FUNCTION_INFO*)&fn_info_raw; // and then convert to RUNTIME_FUNCTION_INFO
221
+ funcs.insert ({ fn_ea, fn_info });
221
222
222
- // Delete useless .pdata -> fn xref
223
- del_dref (seg_addr + offset, fn);
223
+ // Delete useless .pdata -> fn xref
224
+ del_dref (seg_addr + offset, fn_ea);
225
+ }
224
226
225
227
offset += 8 ;
226
228
}
@@ -236,12 +238,25 @@ void pe_add_sections(XEXFile& file)
236
238
237
239
show_wait_box (msg_text);
238
240
239
- // Iterate over functions in reverse, so hopefully they'll be marked with correct lengths
240
241
size_t num = 0 ;
241
- for (std::vector< uint32_t >::reverse_iterator i = funcs. rbegin (); i != funcs. rend (); ++i )
242
+ for (auto & kvp : funcs)
242
243
{
243
- create_insn (*i);
244
- add_func (*i);
244
+ if (!get_fchunk (kvp.first ))
245
+ {
246
+ if (create_insn (kvp.first ))
247
+ {
248
+ show_auto (kvp.first );
249
+
250
+ // Don't create function for savevmx/restvmx
251
+ auto fn_type = kvp.second .RuntimeFunctionType ();
252
+ if (fn_type != xex::RuntimeFunctionType::SaveMillicode && fn_type != xex::RuntimeFunctionType::RestoreMillicode)
253
+ {
254
+ func_t fn (kvp.first , kvp.first + (kvp.second .FunctionLength * 4 ));
255
+ add_func_ex (&fn);
256
+ }
257
+ }
258
+ }
259
+
245
260
if (user_cancelled ())
246
261
break ;
247
262
0 commit comments