[SDK:TOOLS] Add --driver option to pefixup

For now, this adds IMAGE_SCN_MEM_DISCARDABLE to the INIT section, and IMAGE_SCN_MEM_NOT_PAGED to sections which are not named PAGE or .reloc
This commit is contained in:
Jérôme Gardou 2021-02-24 10:14:40 +01:00 committed by Jérôme Gardou
parent 56b1baa3dd
commit 5489efcb1a
2 changed files with 74 additions and 13 deletions

View file

@ -308,7 +308,7 @@ endif()
function(fixup_load_config _target)
add_custom_command(TARGET ${_target} POST_BUILD
COMMAND native-pefixup "$<TARGET_FILE:${_target}>"
COMMAND native-pefixup --loadconfig "$<TARGET_FILE:${_target}>"
COMMENT "Patching in LOAD_CONFIG"
DEPENDS native-pefixup)
endfunction()

View file

@ -24,6 +24,12 @@
static const char* g_ApplicationName;
static const char* g_Target;
enum fixup_mode
{
MODE_LOADCONFIG,
MODE_DRIVER
};
void *rva_to_ptr(unsigned char *buffer, PIMAGE_NT_HEADERS nt_header, DWORD rva)
{
unsigned int i;
@ -121,6 +127,47 @@ static int add_loadconfig(unsigned char *buffer, PIMAGE_NT_HEADERS nt_header)
return 1;
}
static int driver_fixup(unsigned char *buffer, PIMAGE_NT_HEADERS nt_header)
{
/* GNU LD just doesn't know what a driver is, and has notably no idea of paged vs non-paged sections */
for (unsigned i = 0; i < nt_header->FileHeader.NumberOfSections; i++)
{
PIMAGE_SECTION_HEADER Section = IMAGE_FIRST_SECTION(nt_header) + i;
/* Known sections which can be discarded */
if (strncasecmp((char*)Section->Name, "INIT", 4) == 0)
{
Section->Characteristics |= IMAGE_SCN_MEM_DISCARDABLE;
continue;
}
/* Known sections which can be paged */
if ((strncasecmp((char*)Section->Name, "PAGE", 4) == 0)
|| (strncasecmp((char*)Section->Name, ".reloc", 6) == 0))
{
continue;
}
/* If it's discardable, don't set the flag */
if (Section->Characteristics & IMAGE_SCN_MEM_DISCARDABLE)
continue;
Section->Characteristics |= IMAGE_SCN_MEM_NOT_PAGED;
}
return 0;
}
static
void
print_usage(void)
{
printf("Usage: %s <mode> <filename>\n", g_ApplicationName);
printf("Where <mode> is on of the following:\n");
printf(" --loadconfig Fix the LOAD_CONFIG directory entry\n");
printf(" --driver Fix code and data sections for driver images\n");
}
int main(int argc, char **argv)
{
FILE* file;
@ -128,19 +175,34 @@ int main(int argc, char **argv)
unsigned char *buffer;
PIMAGE_DOS_HEADER dos_header;
int result = 1;
enum fixup_mode mode;
g_ApplicationName = argv[0];
if (argc < 2)
if (argc != 3)
{
printf("Usage: %s <filename>\n", g_ApplicationName);
print_usage();
return 1;
}
g_Target = argv[1];
if (strcmp(argv[1], "--loadconfig") == 0)
{
mode = MODE_LOADCONFIG;
}
else if (strcmp(argv[1], "--driver") == 0)
{
mode = MODE_DRIVER;
}
else
{
print_usage();
return 1;
}
g_Target = argv[2];
/* Read the whole file to memory. */
file = fopen(argv[1], "r+b");
file = fopen(g_Target, "r+b");
if (!file)
{
fprintf(stderr, "%s ERROR: Can't open '%s'.\n", g_ApplicationName, g_Target);
@ -180,20 +242,19 @@ int main(int argc, char **argv)
if (nt_header->Signature == IMAGE_NT_SIGNATURE)
{
if (!add_loadconfig(buffer, nt_header))
if (mode == MODE_LOADCONFIG)
result = add_loadconfig(buffer, nt_header);
else
result = driver_fixup(buffer, nt_header);
if (!result)
{
/* Success. Fix checksum and write to file */
fix_checksum(buffer, len, nt_header);
/* We could 'optimize by only writing the changed parts, but keep it simple for now */
fseek(file, 0, SEEK_SET);
fwrite(buffer, 1, len, file);
/* Success */
result = 0;
}
else
{
/* Error already printed inside add_loadconfig */
}
}
else