mirror of
git://repo.or.cz/tinycc.git
synced 2026-06-17 15:44:18 +08:00
pe: add dll characteristic linker options
Add PE linker switches to set and clear DYNAMIC_BASE, NX_COMPAT, HIGH_ENTROPY_VA and TERMINAL_SERVER_AWARE without changing x86/x64 defaults. HIGH_ENTROPY_VA is limited to 64-bit PE targets and implies DYNAMIC_BASE; clearing DYNAMIC_BASE also clears HIGH_ENTROPY_VA. When DYNAMIC_BASE is requested for an executable, emit base relocations and clear RELOCS_STRIPPED so Windows ASLR can relocate the image. Keep the existing ARM64 default hardening flags.
This commit is contained in:
parent
37b7247796
commit
1a54e47dda
40
libtcc.c
40
libtcc.c
@ -1406,6 +1406,20 @@ succ:
|
|||||||
|
|
||||||
static void args_parser_add_file(TCCState *s, const char* filename, int filetype);
|
static void args_parser_add_file(TCCState *s, const char* filename, int filetype);
|
||||||
|
|
||||||
|
#ifdef TCC_TARGET_PE
|
||||||
|
static void tcc_pe_set_dll_characteristics(TCCState *s, unsigned flags)
|
||||||
|
{
|
||||||
|
s->pe_dll_characteristics |= flags;
|
||||||
|
s->pe_dll_characteristics_clear &= ~flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void tcc_pe_clear_dll_characteristics(TCCState *s, unsigned flags)
|
||||||
|
{
|
||||||
|
s->pe_dll_characteristics &= ~flags;
|
||||||
|
s->pe_dll_characteristics_clear |= flags;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* set linker options */
|
/* set linker options */
|
||||||
static int tcc_set_linker(TCCState *s, const char *optarg)
|
static int tcc_set_linker(TCCState *s, const char *optarg)
|
||||||
{
|
{
|
||||||
@ -1475,7 +1489,31 @@ static int tcc_set_linker(TCCState *s, const char *optarg)
|
|||||||
s->znodelete = 1;
|
s->znodelete = 1;
|
||||||
#ifdef TCC_TARGET_PE
|
#ifdef TCC_TARGET_PE
|
||||||
} else if (link_option(&o, "large-address-aware")) {
|
} else if (link_option(&o, "large-address-aware")) {
|
||||||
s->pe_characteristics |= 0x20;
|
s->pe_characteristics |= PE_IMAGE_FILE_LARGE_ADDRESS_AWARE;
|
||||||
|
} else if (link_option(&o, "dynamicbase")) {
|
||||||
|
tcc_pe_set_dll_characteristics(s, PE_DLLCHARACTERISTICS_DYNAMIC_BASE);
|
||||||
|
} else if (link_option(&o, "disable-dynamicbase|no-dynamicbase")) {
|
||||||
|
tcc_pe_clear_dll_characteristics(s,
|
||||||
|
PE_DLLCHARACTERISTICS_DYNAMIC_BASE |
|
||||||
|
PE_DLLCHARACTERISTICS_HIGH_ENTROPY_VA);
|
||||||
|
} else if (link_option(&o, "nxcompat")) {
|
||||||
|
tcc_pe_set_dll_characteristics(s, PE_DLLCHARACTERISTICS_NX_COMPAT);
|
||||||
|
} else if (link_option(&o, "disable-nxcompat|no-nxcompat")) {
|
||||||
|
tcc_pe_clear_dll_characteristics(s, PE_DLLCHARACTERISTICS_NX_COMPAT);
|
||||||
|
} else if (link_option(&o, "high-entropy-va")) {
|
||||||
|
# if defined(TCC_TARGET_X86_64) || defined(TCC_TARGET_ARM64)
|
||||||
|
tcc_pe_set_dll_characteristics(s,
|
||||||
|
PE_DLLCHARACTERISTICS_HIGH_ENTROPY_VA |
|
||||||
|
PE_DLLCHARACTERISTICS_DYNAMIC_BASE);
|
||||||
|
# else
|
||||||
|
goto err;
|
||||||
|
# endif
|
||||||
|
} else if (link_option(&o, "disable-high-entropy-va|no-high-entropy-va")) {
|
||||||
|
tcc_pe_clear_dll_characteristics(s, PE_DLLCHARACTERISTICS_HIGH_ENTROPY_VA);
|
||||||
|
} else if (link_option(&o, "tsaware")) {
|
||||||
|
tcc_pe_set_dll_characteristics(s, PE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE);
|
||||||
|
} else if (link_option(&o, "disable-tsaware|no-tsaware")) {
|
||||||
|
tcc_pe_clear_dll_characteristics(s, PE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE);
|
||||||
} else if (link_option(&o, "file-alignment=")) {
|
} else if (link_option(&o, "file-alignment=")) {
|
||||||
s->pe_file_align = strtoul(o.arg, &end, 16);
|
s->pe_file_align = strtoul(o.arg, &end, 16);
|
||||||
} else if (link_option(&o, "stack=")) {
|
} else if (link_option(&o, "stack=")) {
|
||||||
|
|||||||
@ -386,6 +386,15 @@ Set type for PE (Windows) executables.
|
|||||||
@item -Wl,-[Ttext=# | section-alignment=# | file-alignment=# | image-base=# | stack=#]
|
@item -Wl,-[Ttext=# | section-alignment=# | file-alignment=# | image-base=# | stack=#]
|
||||||
Modify executable layout.
|
Modify executable layout.
|
||||||
|
|
||||||
|
@item -Wl,-[dynamicbase | nxcompat | high-entropy-va | tsaware]
|
||||||
|
@item -Wl,-[no-dynamicbase | no-nxcompat | no-high-entropy-va | no-tsaware]
|
||||||
|
@item -Wl,-[disable-dynamicbase | disable-nxcompat | disable-high-entropy-va | disable-tsaware]
|
||||||
|
Set or clear PE (Windows) executable header hardening flags. The
|
||||||
|
@option{-Wl,-high-entropy-va} option is supported on x86-64 and ARM64 PE
|
||||||
|
targets and implies @option{-Wl,-dynamicbase}. Clearing dynamicbase also
|
||||||
|
clears high-entropy-va. When @option{-Wl,-dynamicbase} is used for an
|
||||||
|
executable, TCC also enables base relocation emission for Windows ASLR.
|
||||||
|
|
||||||
@item -Wl,-Bsymbolic
|
@item -Wl,-Bsymbolic
|
||||||
Set DT_SYMBOLIC tag.
|
Set DT_SYMBOLIC tag.
|
||||||
|
|
||||||
|
|||||||
11
tcc.h
11
tcc.h
@ -727,6 +727,15 @@ struct sym_attr {
|
|||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#ifdef TCC_TARGET_PE
|
||||||
|
#define PE_IMAGE_FILE_RELOCS_STRIPPED 0x0001
|
||||||
|
#define PE_IMAGE_FILE_LARGE_ADDRESS_AWARE 0x0020
|
||||||
|
#define PE_DLLCHARACTERISTICS_HIGH_ENTROPY_VA 0x0020
|
||||||
|
#define PE_DLLCHARACTERISTICS_DYNAMIC_BASE 0x0040
|
||||||
|
#define PE_DLLCHARACTERISTICS_NX_COMPAT 0x0100
|
||||||
|
#define PE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE 0x8000
|
||||||
|
#endif
|
||||||
|
|
||||||
struct TCCState {
|
struct TCCState {
|
||||||
unsigned char verbose; /* if true, display some information during compilation */
|
unsigned char verbose; /* if true, display some information during compilation */
|
||||||
unsigned char nostdinc; /* if true, no standard headers are added */
|
unsigned char nostdinc; /* if true, no standard headers are added */
|
||||||
@ -939,6 +948,8 @@ struct TCCState {
|
|||||||
/* PE info */
|
/* PE info */
|
||||||
int pe_subsystem;
|
int pe_subsystem;
|
||||||
unsigned pe_characteristics;
|
unsigned pe_characteristics;
|
||||||
|
unsigned pe_dll_characteristics;
|
||||||
|
unsigned pe_dll_characteristics_clear;
|
||||||
unsigned pe_file_align;
|
unsigned pe_file_align;
|
||||||
unsigned pe_stack_size;
|
unsigned pe_stack_size;
|
||||||
addr_t pe_imagebase;
|
addr_t pe_imagebase;
|
||||||
|
|||||||
40
tccpe.c
40
tccpe.c
@ -238,16 +238,16 @@ typedef struct _IMAGE_BASE_RELOCATION {
|
|||||||
#define IMAGE_SIZEOF_BASE_RELOCATION 8
|
#define IMAGE_SIZEOF_BASE_RELOCATION 8
|
||||||
|
|
||||||
#ifndef IMAGE_DLLCHARACTERISTICS_HIGH_ENTROPY_VA
|
#ifndef IMAGE_DLLCHARACTERISTICS_HIGH_ENTROPY_VA
|
||||||
#define IMAGE_DLLCHARACTERISTICS_HIGH_ENTROPY_VA 0x0020
|
#define IMAGE_DLLCHARACTERISTICS_HIGH_ENTROPY_VA PE_DLLCHARACTERISTICS_HIGH_ENTROPY_VA
|
||||||
#endif
|
#endif
|
||||||
#ifndef IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE
|
#ifndef IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE
|
||||||
#define IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE 0x0040
|
#define IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE PE_DLLCHARACTERISTICS_DYNAMIC_BASE
|
||||||
#endif
|
#endif
|
||||||
#ifndef IMAGE_DLLCHARACTERISTICS_NX_COMPAT
|
#ifndef IMAGE_DLLCHARACTERISTICS_NX_COMPAT
|
||||||
#define IMAGE_DLLCHARACTERISTICS_NX_COMPAT 0x0100
|
#define IMAGE_DLLCHARACTERISTICS_NX_COMPAT PE_DLLCHARACTERISTICS_NX_COMPAT
|
||||||
#endif
|
#endif
|
||||||
#ifndef IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE
|
#ifndef IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE
|
||||||
#define IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE 0x8000
|
#define IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE PE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define IMAGE_REL_BASED_ABSOLUTE 0
|
#define IMAGE_REL_BASED_ABSOLUTE 0
|
||||||
@ -275,6 +275,21 @@ typedef struct _IMAGE_BASE_RELOCATION {
|
|||||||
#endif /* ndef IMAGE_NT_SIGNATURE */
|
#endif /* ndef IMAGE_NT_SIGNATURE */
|
||||||
/* ----------------------------------------------------------- */
|
/* ----------------------------------------------------------- */
|
||||||
|
|
||||||
|
static WORD pe_get_dll_characteristics(TCCState *s1)
|
||||||
|
{
|
||||||
|
unsigned v = 0;
|
||||||
|
|
||||||
|
#ifdef TCC_TARGET_ARM64
|
||||||
|
v = PE_DLLCHARACTERISTICS_HIGH_ENTROPY_VA |
|
||||||
|
PE_DLLCHARACTERISTICS_DYNAMIC_BASE |
|
||||||
|
PE_DLLCHARACTERISTICS_NX_COMPAT |
|
||||||
|
PE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE;
|
||||||
|
#endif
|
||||||
|
v |= s1->pe_dll_characteristics;
|
||||||
|
v &= ~s1->pe_dll_characteristics_clear;
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
#ifndef IMAGE_FILE_MACHINE_ARM64
|
#ifndef IMAGE_FILE_MACHINE_ARM64
|
||||||
#define IMAGE_FILE_MACHINE_ARM64 0xAA64
|
#define IMAGE_FILE_MACHINE_ARM64 0xAA64
|
||||||
#endif
|
#endif
|
||||||
@ -725,14 +740,7 @@ static int pe_write(struct pe_info *pe)
|
|||||||
0x00000200, /*DWORD SizeOfHeaders; */
|
0x00000200, /*DWORD SizeOfHeaders; */
|
||||||
0x00000000, /*DWORD CheckSum; */
|
0x00000000, /*DWORD CheckSum; */
|
||||||
0x0002, /*WORD Subsystem; */
|
0x0002, /*WORD Subsystem; */
|
||||||
#if defined(TCC_TARGET_ARM64)
|
|
||||||
IMAGE_DLLCHARACTERISTICS_HIGH_ENTROPY_VA |
|
|
||||||
IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE |
|
|
||||||
IMAGE_DLLCHARACTERISTICS_NX_COMPAT |
|
|
||||||
IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE,
|
|
||||||
#else
|
|
||||||
0x0000, /*WORD DllCharacteristics; */
|
0x0000, /*WORD DllCharacteristics; */
|
||||||
#endif
|
|
||||||
0x00100000, /*DWORD SizeOfStackReserve; */
|
0x00100000, /*DWORD SizeOfStackReserve; */
|
||||||
0x00001000, /*DWORD SizeOfStackCommit; */
|
0x00001000, /*DWORD SizeOfStackCommit; */
|
||||||
0x00100000, /*DWORD SizeOfHeapReserve; */
|
0x00100000, /*DWORD SizeOfHeapReserve; */
|
||||||
@ -853,11 +861,14 @@ static int pe_write(struct pe_info *pe)
|
|||||||
pe_header.opthdr.SizeOfHeaders = pe->sizeofheaders;
|
pe_header.opthdr.SizeOfHeaders = pe->sizeofheaders;
|
||||||
pe_header.opthdr.ImageBase = pe->imagebase;
|
pe_header.opthdr.ImageBase = pe->imagebase;
|
||||||
pe_header.opthdr.Subsystem = pe->subsystem;
|
pe_header.opthdr.Subsystem = pe->subsystem;
|
||||||
|
pe_header.opthdr.DllCharacteristics = pe_get_dll_characteristics(s1);
|
||||||
if (s1->pe_stack_size)
|
if (s1->pe_stack_size)
|
||||||
pe_header.opthdr.SizeOfStackReserve = s1->pe_stack_size;
|
pe_header.opthdr.SizeOfStackReserve = s1->pe_stack_size;
|
||||||
if (PE_DLL == pe->type)
|
if (PE_DLL == pe->type)
|
||||||
pe_header.filehdr.Characteristics = CHARACTERISTICS_DLL;
|
pe_header.filehdr.Characteristics = CHARACTERISTICS_DLL;
|
||||||
pe_header.filehdr.Characteristics |= s1->pe_characteristics;
|
pe_header.filehdr.Characteristics |= s1->pe_characteristics;
|
||||||
|
if (pe->reloc)
|
||||||
|
pe_header.filehdr.Characteristics &= ~PE_IMAGE_FILE_RELOCS_STRIPPED;
|
||||||
|
|
||||||
if (pe->coffsym) {
|
if (pe->coffsym) {
|
||||||
pe_add_coffsym(pe);
|
pe_add_coffsym(pe);
|
||||||
@ -1280,11 +1291,8 @@ static int pe_assign_addresses (struct pe_info *pe)
|
|||||||
Section *s;
|
Section *s;
|
||||||
TCCState *s1 = pe->s1;
|
TCCState *s1 = pe->s1;
|
||||||
|
|
||||||
if (PE_DLL == pe->type
|
if (PE_DLL == pe->type ||
|
||||||
#ifdef TCC_TARGET_ARM64
|
(pe_get_dll_characteristics(s1) & PE_DLLCHARACTERISTICS_DYNAMIC_BASE))
|
||||||
|| PE_EXE == pe->type || PE_GUI == pe->type
|
|
||||||
#endif
|
|
||||||
)
|
|
||||||
pe->reloc = new_section(s1, ".reloc", SHT_PROGBITS, 0);
|
pe->reloc = new_section(s1, ".reloc", SHT_PROGBITS, 0);
|
||||||
//pe->thunk = new_section(s1, ".iedat", SHT_PROGBITS, SHF_ALLOC);
|
//pe->thunk = new_section(s1, ".iedat", SHT_PROGBITS, SHF_ALLOC);
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user