Decompile most of the code involved in generating dep files

This commit is contained in:
mid-kid 2024-11-04 00:37:13 +01:00
parent e2e96737b9
commit 6a04657b6f
7 changed files with 236 additions and 46 deletions

View File

@ -1,8 +1,9 @@
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "include.h"
// This function mallocs some memory without clearing it, and reads from it,
// which causes the behavior (and compilation output) to depend on it.
//
@ -11,22 +12,6 @@
#define SKREW_HACK01
struct STRUC_0063a828 {
struct STRUC_0063a828 *next;
int _unk1[1];
struct STRUC_0063a828 *unk_8;
struct STRUC_0063a828 *unk_c;
int _unk2[3];
int unk_1c;
};
extern int DAT_0063a798; // 0x0063a798
extern struct STRUC_0063a828 *DAT_0063a828;
extern struct STRUC_0063a828 **DAT_0063ccb0;
extern uint32_t **DAT_0063ccf0; // 0x0063ccf0
void *prog_malloc(size_t size); // 0x00442550
void FUN_004f8b60(void);
void bitarr_cpy(uint32_t *dst, uint32_t *src, int len); // 0x00581750
int bitarr_cpycmp(uint32_t *dst, uint32_t *src, int len); // 0x00581790
void bitarr_set(uint32_t *dst, int len, uint32_t val); // 0x005817d0

150
patch/depfile_build.c Normal file
View File

@ -0,0 +1,150 @@
#include <stddef.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "include.h"
__stdcall char *depfile_get_target(char *path, char *dir, char *dest, unsigned dest_size); // 0x004178f0
// TODO
__cdecl void depfile_get_header(char *param_1, int param_2, char *param_3); // 0x0043c010
__stdcall char *path_join(char *src, char *dst, size_t size); // 0x004110f0
// 0x00411b90
__stdcall int string_alloc(unsigned size, mwstring *string)
{
string->data = GlobalAlloc(GMEM_ZEROINIT, size);
string->size = size;
if (!string->data) return my_GetLastError();
return 0;
}
// 0x00411bc0
__stdcall int string_realloc(mwstring *string, unsigned size)
{
char *data = GlobalReAlloc(string->data, size, GMEM_ZEROINIT | GMEM_MOVEABLE);
if (!data) {
string->data = NULL;
string->size = 0;
return my_GetLastError();
}
string->data = data;
string->size = size;
return 0;
}
// 0x00411c00
__stdcall char *string_data(mwstring *string)
{
if (GlobalFlags(string->data) == GMEM_INVALID_HANDLE) {
return NULL;
}
return string->data;
}
// 0x00411c80
__stdcall int string_size(mwstring *string, unsigned *out)
{
if (GlobalFlags(string->data) == GMEM_INVALID_HANDLE) {
*out = 0;
return ERROR_NOT_ENOUGH_MEMORY;
}
*out = string->size;
return 0;
}
// 0x00417ea0
__stdcall int string_append(mwstring *string, char *data, unsigned size)
{
int rv;
unsigned cur_size;
rv = string_size(string, &cur_size);
if (rv) return rv;
rv = string_realloc(string, cur_size + size);
if (rv) return rv;
char *cur_data = string_data(string);
if (cur_data != NULL) {
memcpy(cur_data + cur_size, data, size);
}
return 0;
}
// 0x0043c880
__cdecl char *depfile_escape_spaces(int doit, char *dst, char *src)
{
char *s = src;
char *d = dst;
if (!doit) return src;
while (*s) {
if (*s == ' ') *d++ = '\\';
*d++ = *src++;
}
*d = '\0';
return dst;
}
// 0x0043c8d0
__cdecl void depfile_build(char *header_struct, char *depfile_struct, mwstring *string)
{
int cur_header, num_headers;
char strbuf[PATH_MAX * 2];
char escape_buf[PATH_MAX * 2 - 4];
if (string_alloc(0, string)) goto outofmem;
num_headers = *(int *)(depfile_struct + 0x870);
char target[PATH_MAX];
depfile_get_target(depfile_struct + 0x423, NULL, target, PATH_MAX);
if (!*target) {
char *source = depfile_struct + 0x1c;
char *source_escaped = depfile_escape_spaces(
strchr(source, ' ') != NULL, escape_buf, source);
sprintf(strbuf, "%s: %s\n", source_escaped, num_headers ? "\\" : "");
if (string_append(string, strbuf, strlen(strbuf))) goto outofmem;
} else {
char *target_escaped = depfile_escape_spaces(
strchr(target, ' ') != NULL, escape_buf, target);
sprintf(strbuf, "%s: ", target_escaped);
if (string_append(string, strbuf, strlen(strbuf))) goto outofmem;
char *source = depfile_struct + 0x1c;
char *source_escaped = depfile_escape_spaces(
strchr(source, ' ') != NULL, escape_buf, source);
sprintf(strbuf, "%s %s\n", source_escaped, num_headers ? "\\" : "");
if (string_append(string, strbuf, strlen(strbuf))) goto outofmem;
}
for (cur_header = 0; cur_header < *(int *)(depfile_struct + 0x870);
cur_header++) {
num_headers--;
char header[PATH_MAX * 2 - 4];
char header_full[PATH_MAX];
depfile_get_header(header_struct,
(*(int **)(depfile_struct + 0x878))[cur_header], header);
path_join(header, header_full, PATH_MAX);
char *header_escaped = depfile_escape_spaces(
strchr(header_full, ' ') != NULL, escape_buf, header_full);
sprintf(strbuf, "\t%s %s\n", header_escaped, num_headers ? "\\" : "");
if (string_append(string, strbuf, strlen(strbuf))) goto outofmem;
}
return;
outofmem:
fprintf(stderr, "\n*** Out of memory\n");
exit(233);
}

View File

@ -61,4 +61,11 @@ addr_DAT_0063ccb0 = 0x63ccb0
addr_DAT_0063ccf0 = 0x63ccf0
addr_depfile_build = 0x0043c8d0
code_depfile_build = addr_depfile_build - pe_text_addr + pe_text_off
code_depfile_build.end = code_depfile_build + 10
addr_depfile_get_target = 0x004178f0
addr_depfile_get_header = 0x0043c010
addr_path_join = 0x004110f0
.include "patch.i"

32
patch/include.h Normal file
View File

@ -0,0 +1,32 @@
#pragma once
#include <stdint.h>
// WINE headers
#include "windef.h"
#include "winbase.h"
DWORD WINAPI my_GetLastError(void);
#define PATH_MAX 0x104
struct STRUC_0063a828 {
struct STRUC_0063a828 *next;
int _unk1[1];
struct STRUC_0063a828 *unk_8;
struct STRUC_0063a828 *unk_c;
int _unk2[3];
int unk_1c;
};
typedef struct {
char *data;
unsigned size;
} mwstring;
extern int DAT_0063a798; // 0x0063a798
extern struct STRUC_0063a828 *DAT_0063a828; // 0x0063a828
extern struct STRUC_0063a828 **DAT_0063ccb0; // 0x0063ccb0
extern uint32_t **DAT_0063ccf0; // 0x0063ccf0
__cdecl void *prog_malloc(size_t size); // 0x00442550
__cdecl void FUN_004f8b60(void); // 0x004f8b60

View File

@ -4,7 +4,8 @@ fs = import('fs')
sources_c = [
'env.c',
'FUN_00505340.c'
'FUN_00505340.c',
'depfile_build.c'
]
c_args = [
@ -15,7 +16,8 @@ c_args = [
]
patch_common = static_library('patch_common', sources_c,
c_args: c_args)
c_args: c_args,
dependencies: wine_headers)
# Patch listing

View File

@ -53,17 +53,14 @@ incbin patch.end, (pe_text_off + pe_text_len - patch.end)
wjmp patch_getenv
.endm
.macro patch_memreuse01_hook
call jump_patch_memreuse01_hook
.endm
.macro patch_memreuse01_exit
jmp jump_patch_memreuse01_exit
.endm
.macro patch_FUN_00505340
wjmp FUN_00505340
.endm
.macro patch_depfile_build
wjmp depfile_build
.endm
# The actual code
.section .patch_pe_text, "ax"
pe_text:
@ -72,34 +69,21 @@ pe_text:
patch code_init_args, patch_init_args
patch code_init_envp, patch_init_envp
patch code_getenv, patch_getenv
.ifdef code_memreuse01
#patch code_memreuse01_hook, patch_memreuse01_hook
#patch code_memreuse01_exit, patch_memreuse01_exit
.ifdef code_depfile_build
patch code_depfile_build, patch_depfile_build
.endif
.ifdef code_FUN_00505340
patch code_FUN_00505340, patch_FUN_00505340
.endif
patch_end
.ifdef code_memreuse01
jump_patch_memreuse01:
wcall patch_memreuse01_hook
lea ecx, [ebx + 0x1f]
sar ecx, 5
lea ecx, [ecx * 4]
ret
jump_patch_memreuse01_exit:
wcall patch_memreuse01_exit
add esp, 8
pop ebp
pop edi
pop esi
pop ebx
ret
.endif
var prog_malloc addr_prog_malloc
var FUN_004f8b60 addr_FUN_004f8b60
.ifdef code_depfile_build
var depfile_get_target addr_depfile_get_target
var depfile_get_header addr_depfile_get_header
var path_join addr_path_join
.endif
var DAT_0063a798 addr_DAT_0063a798
var DAT_0063a828 addr_DAT_0063a828

View File

@ -356,6 +356,35 @@ unsigned find_memreuse01(const struct file *binary, const struct loc **res)
return 7;
}
unsigned find_depfile(const struct file *binary, const struct loc **res)
{
const struct scan code[] = {
DEF_SCAN(0,
0x53, // push ebx
0x56, // push esi
0x57, // push edi
0x55, // push ebp
0x81, 0xec, 0x1c, 0x08, 0x00, 0x00, // sub esp, 0x81c
0x8b, 0x9c, 0x24, 0x34, 0x08, 0x00, 0x00 // mov ebx, dword ptr [esp + u32]
),
END_SCAN
};
static struct loc loc[] = {
{.name = "depfile_build"},
};
const unsigned char *pos = scan(binary, code, 0);
if (!pos) return 0;
size_t off = pos - binary->data;
loc[0].start = off + code[0].off;
loc[0].end = off + code[0].off + code[0].size;
*res = loc;
return 1;
}
typedef unsigned (*funcs_t)(const struct file *, const struct loc **);
static const funcs_t funcs[] = {
find_fs,
@ -363,6 +392,7 @@ static const funcs_t funcs[] = {
find_getenv,
find_findexe,
find_memreuse01,
find_depfile,
NULL
};