review some recent changes

tccrun.c:
- simplify usage of VirtualAlloc on win32/64
  from 6728a64f1b
tccpe.c:
- revert changes to pe_create_pdb()
  (doesn't work and/or too much complication)
  from 37b7247796
- reduce #ifdef amount
tccgen.c:
- fix fix for cast to void
  from fad812360b
tccelf.c:
- put create_riscv_attribute_section() into right place
  from c77339ab41
tcc.h/libtcc.c:
- simplify link-option parser for pe dll_characteristics
  from 1a54e47dda
i386-gen.c:
- fix tls
  from 8502540b4a
workflow/build.yml:
- add i386-linux
- disable riscv64-linux-native (seems not supported currently)
This commit is contained in:
grischka 2026-06-05 08:59:57 +02:00
parent a338258d30
commit 7f7845cd7e
13 changed files with 178 additions and 310 deletions

View File

@ -34,16 +34,13 @@ jobs:
timeout-minutes: 6
steps:
- uses: actions/checkout@v4
- name: build tcc (x86_64-win32)
- name: build & test (x86_64-win32)
shell: cmd
run: |
cd win32
for /f "delims=" %%i in ('vswhere.exe -latest -property installationPath') do call "%%i\VC\Auxiliary\Build\vcvarsall.bat" amd64
call build-tcc.bat -c cl -t x86_64
- name: test (x86_64-win32)
shell: cmd
run: |
cd tests
cd ..\tests
call test-win32.bat all -k
test-i386-win32:
@ -51,16 +48,13 @@ jobs:
timeout-minutes: 6
steps:
- uses: actions/checkout@v4
- name: build tcc (i386-win32)
- name: build & test (i386-win32)
shell: cmd
run: |
cd win32
for /f "delims=" %%i in ('vswhere.exe -latest -property installationPath') do call "%%i\VC\Auxiliary\Build\vcvarsall.bat" x86
call build-tcc.bat -c cl -t i386
- name: test (i386-win32)
shell: cmd
run: |
cd tests
cd ..\tests
call test-win32.bat -p c:\mingw32\bin all -k
test-arm64-win32:
@ -72,9 +66,8 @@ jobs:
shell: cmd
run: |
cd win32
for /f "delims=" %%i in ('vswhere.exe -latest -property installationPath') do call "%%i\VC\Auxiliary\Build\vcvarsall.bat" amd64_arm64
for /f "delims=" %%i in ('vswhere.exe -latest -property installationPath') do call "%%i\VC\Auxiliary\Build\vcvarsall.bat" arm64
call build-tcc.bat -c cl -t arm64
set "PATH=C:\Program Files\LLVM\bin;%CD%;%PATH%"
cd ..\tests
call test-win32.bat -c clang all -k
@ -132,12 +125,25 @@ jobs:
echo "::endgroup::" # flatten 'run container'
./configure && make && make test -k
test-riscv64-linux-native:
runs-on: ubuntu-24.04-riscv
timeout-minutes: 8
# test-riscv64-linux-native:
# runs-on: ubuntu-24.04-riscv
# timeout-minutes: 8
# steps:
# - uses: actions/checkout@v4
# - name: make & test tcc (riscv64-linux native)
# run: |
# uname -m # riscv64
# ./configure && make && make test -k
test-i386-linux:
runs-on: ubuntu-latest
timeout-minutes: 3
steps:
- uses: actions/checkout@v4
- name: make & test tcc (riscv64-linux native)
- name: install i386-gcc
run: |
uname -m # riscv64
./configure && make && make test -k
sudo dpkg --add-architecture i386
sudo apt-get update -q -y
sudo apt-get install -q -y gcc-multilib libc6-dev:i386
- name: make & test tcc (i386-linux)
run: ./configure --cpu=i386 --cc="gcc -m32" && make && make test -k

View File

@ -439,7 +439,7 @@ ST_FUNC void store(int r, SValue *v)
} else
#endif
if ((fr & VT_SYM) && v->sym->type.t & VT_TLS) {
if ((v->r & VT_SYM) && v->sym->type.t & VT_TLS) {
o(0x65); /* gs segment prefix */
o(opc);
o(0x04 | (REG_VALUE(r) << 3)); /* modrm: [sib] | srcreg */
@ -467,7 +467,7 @@ static void gadd_sp(int val)
}
}
#if defined CONFIG_TCC_BCHECK || defined TCC_TARGET_PE || defined CONFIG_TCC_PIC
#if defined TCC_TARGET_PE || defined CONFIG_TCC_PIC
static void gen_static_call(int v)
{
Sym *sym;

View File

@ -73,7 +73,7 @@ OBJ-arm-vfp = $(OBJ-arm)
OBJ-arm-eabi = $(OBJ-arm)
OBJ-arm-eabihf = $(OBJ-arm)
OBJ-arm-wince = $(ARM_O) $(WIN_O)
OBJ-riscv64 = $(RISCV64_O) lib-riscv.o $(LIN_O)
OBJ-riscv64 = $(RISCV64_O) armflush.o $(LIN_O)
OBJ-extra = $(filter $(EXTRA_O),$(OBJ-$T))
OBJ-libtcc1 = $(addprefix $(X),$(filter-out $(OBJ-extra),$(OBJ-$T)))

View File

@ -61,4 +61,10 @@ void __clear_cache(void *beg, void *end)
}
/* ------------------------------------------------------------- */
#elif defined __riscv
void __clear_cache(void *beg, void *end)
{
__riscv64_clear_cache(beg, end);
}
#endif

View File

@ -1,20 +0,0 @@
/*
* TCC runtime library for riscv64.
*
* Copyright (c) 2026
*
* Copying and distribution of this file, with or without modification,
* are permitted in any medium without royalty provided the copyright
* notice and this notice are preserved. This file is offered as-is,
* without any warranty.
*/
/* ------------------------------------------------------------- */
/* __clear_cache is used in tccrun.c. It is a built-in
intrinsic with gcc. However tcc in order to compile
itself needs this function */
void __clear_cache(void *beg, void *end)
{
__riscv64_clear_cache(beg, end);
}

View File

@ -899,6 +899,9 @@ LIBTCCAPI TCCState *tcc_new(void)
#ifdef TCC_ARM_HARDFLOAT
s->float_abi = ARM_HARD_FLOAT;
#endif
#if defined TCC_TARGET_ARM64 && defined TCC_TARGET_PE
s->pe_dll_characteristics = 0x8160;
#endif
#ifdef CONFIG_NEW_DTAGS
s->enable_new_dtags = 1;
#endif
@ -1365,7 +1368,7 @@ struct lopt {
static int link_option(struct lopt *o, const char *q)
{
const char *p;
int c;
int c, r;
redo:
/* there should be 1 or 2 dashes */
p = o->opt;
@ -1373,6 +1376,16 @@ redo:
return 0;
if (*p == '-')
p++;
r = 1;
if (q[0] == '?') { /* check for no-/disable- prefix */
++q;
if (p[0] == 'n' && p[1] == 'o' && p[2] == '-')
p += 3, r = -1;
#ifdef TCC_TARGET_PE
else if (0 == memcmp(p, "disable-", 8))
p += 8, r = -1;
#endif
}
while ((c = *q) == *p) {
if (c == '\0')
goto succ; /* -Wl,-opt */
@ -1401,24 +1414,13 @@ redo:
succ:
o->arg = p;
//printf("set %s '%s'\n", o->opt, o->arg);
return 1;
return r;
}
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
#define SET_OR_CLEAR(v,f) (v = r > 0 ? v | f : v & ~f)
#define SET_OR_CLEAR_2(v,f1,f2) (v = r > 0 ? v | f1 : v & ~f2)
/* set linker options */
static int tcc_set_linker(TCCState *s, const char *optarg)
@ -1431,6 +1433,7 @@ static int tcc_set_linker(TCCState *s, const char *optarg)
char *end = NULL;
int ignoring = 0;
struct lopt o = {0};
int r;
o.s = s;
o.opt = s->link_argv[s->link_optind];
@ -1481,39 +1484,21 @@ static int tcc_set_linker(TCCState *s, const char *optarg)
s->section_align = strtoul(o.arg, &end, 16);
} else if (link_option(&o, "soname=|install_name=")) {
tcc_set_str(&s->soname, o.arg);
} else if (link_option(&o, "whole-archive")) {
s->filetype |= AFF_WHOLE_ARCHIVE;
} else if (link_option(&o, "no-whole-archive")) {
s->filetype &= ~AFF_WHOLE_ARCHIVE;
} else if (!!(r = link_option(&o, "?whole-archive"))) {
SET_OR_CLEAR(s->filetype, AFF_WHOLE_ARCHIVE);
} else if (link_option(&o, "znodelete")) {
s->znodelete = 1;
#ifdef TCC_TARGET_PE
} else if (link_option(&o, "large-address-aware")) {
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);
s->pe_characteristics |= 0x20;
} else if (!!(r = link_option(&o, "?dynamicbase"))) {
SET_OR_CLEAR_2(s1->pe_dll_characteristics, 0x40, 0x60);
} else if (!!(r = link_option(&o, "?high-entropy-va"))) {
SET_OR_CLEAR_2(s1->pe_dll_characteristics, 0x60, 0x20);
} else if (!!(r = link_option(&o, "?nxcompat"))) {
SET_OR_CLEAR(s1->pe_dll_characteristics, 0x100);
} else if (!!(r = link_option(&o, "?tsaware"))) {
SET_OR_CLEAR(s1->pe_dll_characteristics, 0x8000);
} else if (link_option(&o, "file-alignment=")) {
s->pe_file_align = strtoul(o.arg, &end, 16);
} else if (link_option(&o, "stack=")) {

View File

@ -386,9 +386,7 @@ Set type for PE (Windows) executables.
@item -Wl,-[Ttext=# | section-alignment=# | file-alignment=# | image-base=# | stack=#]
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]
@item -Wl,-(no-|disable-)[dynamicbase | nxcompat | high-entropy-va | 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

10
tcc.h
View File

@ -727,15 +727,6 @@ struct sym_attr {
#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 {
unsigned char verbose; /* if true, display some information during compilation */
unsigned char nostdinc; /* if true, no standard headers are added */
@ -949,7 +940,6 @@ struct TCCState {
int pe_subsystem;
unsigned pe_characteristics;
unsigned pe_dll_characteristics;
unsigned pe_dll_characteristics_clear;
unsigned pe_file_align;
unsigned pe_stack_size;
addr_t pe_imagebase;

View File

@ -2992,6 +2992,10 @@ static int elf_output_file(TCCState *s1, const char *filename)
create_arm_attribute_section (s1);
#endif
#ifdef TCC_TARGET_RISCV64
create_riscv_attribute_section(s1);
#endif
#if TARGETOS_OpenBSD
dyninf.note = create_bsd_note_section (s1, ".note.openbsd.ident", "OpenBSD");
#endif
@ -3172,9 +3176,6 @@ static int elf_output_obj(TCCState *s1, const char *filename)
{
Section *s;
int i, ret, file_offset;
#ifdef TCC_TARGET_RISCV64
create_riscv_attribute_section(s1);
#endif
/* Allocate strings for section names */
alloc_sec_names(s1, 1);
file_offset = (sizeof (ElfW(Ehdr)) + 3) & -4;

View File

@ -3280,6 +3280,8 @@ again:
dbt_bt = dbt & VT_BTYPE;
sbt_bt = sbt & VT_BTYPE;
if (dbt_bt == VT_VOID) {
/* do not confuse backends with VT_VOID in registers */
vpop(), vpushi(0);
goto done;
}
if (sbt_bt == VT_VOID) {

256
tccpe.c
View File

@ -27,54 +27,78 @@
#define stricmp strcasecmp
#define strnicmp strncasecmp
#include <sys/stat.h> /* chmod() */
#else
#include <process.h>
#endif
#ifdef TCC_TARGET_X86_64
# define ADDR3264 ULONGLONG
# define PE_IMAGE_REL IMAGE_REL_BASED_DIR64
#if defined TCC_TARGET_X86_64
# define REL_TYPE_DIRECT R_X86_64_64
# define R_XXX_THUNKFIX R_X86_64_PC32
# define R_XXX_RELATIVE R_X86_64_RELATIVE
# define R_XXX_FUNCCALL R_X86_64_PLT32
# define IMAGE_FILE_MACHINE 0x8664
# define RSRC_RELTYPE 3
# define IMAGE_FILE_MACHINE 0x8664
# define CHARACTERISTICS_EXE 0x022F
# define CHARACTERISTICS_DLL 0x222E
# define IMAGE_BASE_EXE 0x00400000
# define IMAGE_BASE_DLL 0x10000000
# define DLLCHARACTERISTICS 0
# define OS_VER 0x0400
#elif defined TCC_TARGET_ARM
# define ADDR3264 DWORD
# define PE_IMAGE_REL IMAGE_REL_BASED_HIGHLOW
# define REL_TYPE_DIRECT R_ARM_ABS32
# define R_XXX_THUNKFIX R_ARM_ABS32
# define R_XXX_RELATIVE R_ARM_RELATIVE
# define R_XXX_FUNCCALL R_ARM_PC24
# define R_XXX_FUNCCALL2 R_ARM_ABS32
# define IMAGE_FILE_MACHINE 0x01C0
# define RSRC_RELTYPE 7 /* ??? (not tested) */
# define IMAGE_FILE_MACHINE 0x01C0
# define CHARACTERISTICS_EXE 0x010F
# define CHARACTERISTICS_DLL 0x230F
# define IMAGE_BASE_EXE 0x00100000
# define IMAGE_BASE_DLL 0x10000000
# define DLLCHARACTERISTICS 0
# define OS_VER 0x0400
#elif defined TCC_TARGET_ARM64
# define ADDR3264 ULONGLONG
# define PE_IMAGE_REL IMAGE_REL_BASED_DIR64
# define REL_TYPE_DIRECT R_AARCH64_ABS64
# define R_XXX_THUNKFIX R_AARCH64_ABS64
# define R_XXX_RELATIVE R_AARCH64_RELATIVE
# define R_XXX_FUNCCALL R_AARCH64_CALL26
# define IMAGE_FILE_MACHINE 0xAA64
# define RSRC_RELTYPE 3
# define IMAGE_FILE_MACHINE 0xAA64
# define CHARACTERISTICS_EXE 0x0022
# define CHARACTERISTICS_DLL 0x2022
# define IMAGE_BASE_EXE 0x140000000ULL
# define IMAGE_BASE_DLL 0x180000000ULL
# define OS_VER 0x0602
# define DLLCHARACTERISTICS 0x8160
#elif defined TCC_TARGET_I386
# define ADDR3264 DWORD
# define PE_IMAGE_REL IMAGE_REL_BASED_HIGHLOW
# define REL_TYPE_DIRECT R_386_32
# define R_XXX_THUNKFIX R_386_32
# define R_XXX_RELATIVE R_386_RELATIVE
# define R_XXX_FUNCCALL R_386_PC32
# define IMAGE_FILE_MACHINE 0x014C
# define RSRC_RELTYPE 7 /* DIR32NB */
# define IMAGE_FILE_MACHINE 0x014C
# define CHARACTERISTICS_EXE 0x030F
# define CHARACTERISTICS_DLL 0x230E
# define IMAGE_BASE_EXE 0x00400000
# define IMAGE_BASE_DLL 0x10000000
# define OS_VER 0x0400
# define DLLCHARACTERISTICS 0
#endif
#if PTR_SIZE == 8
# define ADDR3264 ULONGLONG
# define PE_MAGIC 0x020B
# define PE_IMAGE_REL IMAGE_REL_BASED_DIR64
#else
# define ADDR3264 DWORD
# define PE_MAGIC 0x010B
# define PE_IMAGE_REL IMAGE_REL_BASED_HIGHLOW
#endif
#ifndef IMAGE_NT_SIGNATURE
/* cross compiler: windows.h was not included */
/* ----------------------------------------------------------- */
/* definitions below are from winnt.h */
@ -107,7 +131,6 @@ typedef struct _IMAGE_DOS_HEADER { /* DOS .EXE header */
} IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER;
#define IMAGE_NT_SIGNATURE 0x00004550 /* PE00 */
#define SIZE_OF_NT_SIGNATURE 4
typedef struct _IMAGE_FILE_HEADER {
WORD Machine;
@ -138,7 +161,7 @@ typedef struct _IMAGE_OPTIONAL_HEADER {
DWORD SizeOfUninitializedData;
DWORD AddressOfEntryPoint;
DWORD BaseOfCode;
#if !defined(TCC_TARGET_X86_64) && !defined(TCC_TARGET_ARM64)
#if PTR_SIZE == 4
DWORD BaseOfData;
#endif
/* NT additional fields. */
@ -237,19 +260,6 @@ typedef struct _IMAGE_BASE_RELOCATION {
#define IMAGE_SIZEOF_BASE_RELOCATION 8
#ifndef IMAGE_DLLCHARACTERISTICS_HIGH_ENTROPY_VA
#define IMAGE_DLLCHARACTERISTICS_HIGH_ENTROPY_VA PE_DLLCHARACTERISTICS_HIGH_ENTROPY_VA
#endif
#ifndef IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE
#define IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE PE_DLLCHARACTERISTICS_DYNAMIC_BASE
#endif
#ifndef IMAGE_DLLCHARACTERISTICS_NX_COMPAT
#define IMAGE_DLLCHARACTERISTICS_NX_COMPAT PE_DLLCHARACTERISTICS_NX_COMPAT
#endif
#ifndef IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE
#define IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE PE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE
#endif
#define IMAGE_REL_BASED_ABSOLUTE 0
#define IMAGE_REL_BASED_HIGH 1
#define IMAGE_REL_BASED_LOW 2
@ -269,34 +279,19 @@ typedef struct _IMAGE_BASE_RELOCATION {
#define IMAGE_SCN_MEM_READ 0x40000000
#define IMAGE_SCN_MEM_WRITE 0x80000000
#define IMAGE_DLLCHARACTERISTICS_HIGH_ENTROPY_VA 0x0020
#define IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE 0x0040
#define IMAGE_DLLCHARACTERISTICS_NX_COMPAT 0x0100
#define IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE 0x8000
#define IMAGE_FILE_RELOCS_STRIPPED 0x0001
#pragma pack(pop)
/* ----------------------------------------------------------- */
#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
#define IMAGE_FILE_MACHINE_ARM64 0xAA64
#endif
#ifndef IMAGE_REL_BASED_DIR64
# define IMAGE_REL_BASED_DIR64 10
#endif
#pragma pack(push, 1)
struct pe_header
{
@ -304,7 +299,7 @@ struct pe_header
BYTE dosstub[0x40];
DWORD nt_sig;
IMAGE_FILE_HEADER filehdr;
#if defined(TCC_TARGET_X86_64) || defined(TCC_TARGET_ARM64)
#if PTR_SIZE == 8
IMAGE_OPTIONAL_HEADER64 opthdr;
#else
#ifdef _WIN64
@ -580,55 +575,17 @@ static void pe_add_coffsym(struct pe_info *pe)
/* Run cv2pdb, available at https://github.com/rainers/cv2pdb. It reads
and strips the dwarf info and creates a <exename>.pdb file instead */
#ifndef _WIN32
static void pe_shell_quote(CString *cmd, const char *arg)
{
cstr_cat(cmd, "'", 1);
while (*arg) {
if (*arg == '\'')
cstr_cat(cmd, "'\\''", 4);
else
cstr_cat(cmd, arg, 1);
++arg;
}
cstr_cat(cmd, "'", 1);
}
#endif
static intptr_t pe_run_cv2pdb(const char *exename)
{
#ifdef _WIN32
const char *argv[] = { "cv2pdb.exe", exename, NULL };
return _spawnvp(_P_WAIT, "cv2pdb.exe", argv);
#else
CString cmd;
intptr_t ret;
cstr_new(&cmd);
cstr_cat(&cmd, "cv2pdb.exe ", -1);
pe_shell_quote(&cmd, exename);
cstr_ccat(&cmd, 0);
ret = system(cmd.data);
cstr_free(&cmd);
return ret;
#endif
}
static void pe_create_pdb(TCCState *s1, const char *exename)
{
size_t len = strlen(exename);
char *pdbfile = tcc_malloc(len + sizeof(".pdb"));
intptr_t r;
strcpy(pdbfile, exename);
strcpy(tcc_fileextension(pdbfile), ".pdb");
r = pe_run_cv2pdb(exename);
char buf[300]; int r;
snprintf(buf, sizeof buf, "cv2pdb.exe \"%s\"", exename);
r = system(buf);
strcpy(tcc_fileextension(strcpy(buf, exename)), ".pdb");
if (r) {
tcc_error_noabort("could not create '%s'\n(need working cv2pdb from https://github.com/rainers/cv2pdb)", pdbfile);
tcc_error_noabort("could not create '%s'\n(need working cv2pdb from https://github.com/rainers/cv2pdb)", buf);
} else if (s1->verbose) {
printf("<- %s\n", pdbfile);
printf("<- %s\n", buf);
}
tcc_free(pdbfile);
}
/*----------------------------------------------------------------------------*/
@ -674,31 +631,12 @@ static int pe_write(struct pe_info *pe)
0x00000000, /*DWORD TimeDateStamp; */
0x00000000, /*DWORD PointerToSymbolTable; */
0x00000000, /*DWORD NumberOfSymbols; */
#if defined(TCC_TARGET_X86_64)
0x00F0, /*WORD SizeOfOptionalHeader; */
0x022F /*WORD Characteristics; */
#define CHARACTERISTICS_DLL 0x222E
#elif defined(TCC_TARGET_I386)
0x00E0, /*WORD SizeOfOptionalHeader; */
0x030F /*WORD Characteristics; */
#define CHARACTERISTICS_DLL 0x230E
#elif defined(TCC_TARGET_ARM)
0x00E0, /*WORD SizeOfOptionalHeader; */
0x010F, /*WORD Characteristics; */
#define CHARACTERISTICS_DLL 0x230F
#elif defined(TCC_TARGET_ARM64)
0x00F0, /*WORD SizeOfOptionalHeader; */
0x0022 /*WORD Characteristics; */
#define CHARACTERISTICS_DLL 0x2022
#endif
},{
0x00E0 + (PTR_SIZE-4)*4, /*WORD SizeOfOptionalHeader; */
CHARACTERISTICS_EXE, /*WORD Characteristics; */
},{
/* IMAGE_OPTIONAL_HEADER opthdr */
/* Standard fields. */
#if defined(TCC_TARGET_X86_64) || defined(TCC_TARGET_ARM64)
0x020B, /*WORD Magic; */
#else
0x010B, /*WORD Magic; */
#endif
PE_MAGIC, /*WORD Magic; */
0x06, /*BYTE MajorLinkerVersion; */
0x00, /*BYTE MinorLinkerVersion; */
0x00000000, /*DWORD SizeOfCode; */
@ -706,45 +644,29 @@ static int pe_write(struct pe_info *pe)
0x00000000, /*DWORD SizeOfUninitializedData; */
0x00000000, /*DWORD AddressOfEntryPoint; */
0x00000000, /*DWORD BaseOfCode; */
#if !defined(TCC_TARGET_X86_64) && !defined(TCC_TARGET_ARM64)
#if PTR_SIZE == 4
0x00000000, /*DWORD BaseOfData; */
#endif
/* NT additional fields. */
#if defined(TCC_TARGET_ARM)
0x00100000, /*DWORD ImageBase; */
#elif defined(TCC_TARGET_ARM64)
0x140000000ULL, /*ULONGLONG ImageBase; */
#else
0x00400000, /*DWORD ImageBase; */
#endif
0x00000000, /*ADDR3264 ImageBase; */
0x00001000, /*DWORD SectionAlignment; */
0x00000200, /*DWORD FileAlignment; */
#if defined(TCC_TARGET_ARM64)
0x0006, /*WORD MajorOperatingSystemVersion; */
0x0002, /*WORD MinorOperatingSystemVersion; */
#else
0x0004, /*WORD MajorOperatingSystemVersion; */
0x0000, /*WORD MinorOperatingSystemVersion; */
#endif
OS_VER >> 8, /*WORD MajorOperatingSystemVersion; */
OS_VER & 255, /*WORD MinorOperatingSystemVersion; */
0x0000, /*WORD MajorImageVersion; */
0x0000, /*WORD MinorImageVersion; */
#if defined(TCC_TARGET_ARM64)
0x0006, /*WORD MajorSubsystemVersion; */
0x0002, /*WORD MinorSubsystemVersion; */
#else
0x0004, /*WORD MajorSubsystemVersion; */
0x0000, /*WORD MinorSubsystemVersion; */
#endif
OS_VER >> 8, /*WORD MajorSubsystemVersion; */
OS_VER & 255, /*WORD MinorSubsystemVersion; */
0x00000000, /*DWORD Win32VersionValue; */
0x00000000, /*DWORD SizeOfImage; */
0x00000200, /*DWORD SizeOfHeaders; */
0x00000000, /*DWORD CheckSum; */
0x0002, /*WORD Subsystem; */
0x0000, /*WORD DllCharacteristics; */
0x00100000, /*DWORD SizeOfStackReserve; */
0x00001000, /*DWORD SizeOfStackCommit; */
0x00100000, /*DWORD SizeOfHeapReserve; */
0x00001000, /*DWORD SizeOfHeapCommit; */
DLLCHARACTERISTICS, /*WORD DllCharacteristics; */
0x00100000, /*ADDR3264 SizeOfStackReserve; */
0x00001000, /*ADDR3264 SizeOfStackCommit; */
0x00100000, /*ADDR3264 SizeOfHeapReserve; */
0x00001000, /*ADDR3264 SizeOfHeapCommit; */
0x00000000, /*DWORD LoaderFlags; */
0x00000010, /*DWORD NumberOfRvaAndSizes; */
@ -799,7 +721,7 @@ static int pe_write(struct pe_info *pe)
break;
case sec_data:
#if !defined(TCC_TARGET_X86_64) && !defined(TCC_TARGET_ARM64)
#if PTR_SIZE == 4
if (!pe_header.opthdr.BaseOfData)
pe_header.opthdr.BaseOfData = addr;
#endif
@ -861,14 +783,14 @@ static int pe_write(struct pe_info *pe)
pe_header.opthdr.SizeOfHeaders = pe->sizeofheaders;
pe_header.opthdr.ImageBase = pe->imagebase;
pe_header.opthdr.Subsystem = pe->subsystem;
pe_header.opthdr.DllCharacteristics = pe_get_dll_characteristics(s1);
pe_header.opthdr.DllCharacteristics = s1->pe_dll_characteristics;
if (s1->pe_stack_size)
pe_header.opthdr.SizeOfStackReserve = s1->pe_stack_size;
if (PE_DLL == pe->type)
pe_header.filehdr.Characteristics = CHARACTERISTICS_DLL;
pe_header.filehdr.Characteristics |= s1->pe_characteristics;
if (pe->reloc)
pe_header.filehdr.Characteristics &= ~PE_IMAGE_FILE_RELOCS_STRIPPED;
pe_header.filehdr.Characteristics &= ~IMAGE_FILE_RELOCS_STRIPPED;
if (pe->coffsym) {
pe_add_coffsym(pe);
@ -1291,8 +1213,8 @@ static int pe_assign_addresses (struct pe_info *pe)
Section *s;
TCCState *s1 = pe->s1;
if (PE_DLL == pe->type ||
(pe_get_dll_characteristics(s1) & PE_DLLCHARACTERISTICS_DYNAMIC_BASE))
if (PE_DLL == pe->type
|| (s1->pe_dll_characteristics & IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE))
pe->reloc = new_section(s1, ".reloc", SHT_PROGBITS, 0);
//pe->thunk = new_section(s1, ".iedat", SHT_PROGBITS, SHF_ALLOC);
@ -1483,14 +1405,10 @@ static int pe_check_symbols(struct pe_info *pe)
offset + 8, R_XXX_THUNKFIX, is->iat_index); // offset to IAT position
#elif defined(TCC_TARGET_ARM64)
p = section_ptr_add(text_section, 24);
/* ldr x16, [pc, #16] */
write32le(p + 0, 0x58000090);
/* ldr x16, [x16] */
write32le(p + 4, 0xf9400210);
/* br x16 */
write32le(p + 8, 0xd61f0200);
/* nop for 8-byte literal alignment */
write32le(p + 12, 0xd503201f);
write32le(p + 0, 0x58000090); /* ldr x16, [pc, #16] */
write32le(p + 4, 0xf9400210); /* ldr x16, [x16] */
write32le(p + 8, 0xd61f0200); /* br x16 */
write32le(p + 12, 0xd503201f); /* nop for alignment */
put_elf_reloc(symtab_section, text_section,
offset + 16, R_XXX_THUNKFIX, is->iat_index);
#else
@ -1716,7 +1634,7 @@ static int get_dllexports(int fd, char **pp)
if (!read_mem(fd, pef_hdroffset, &ih, sizeof ih))
goto the_end;
opt_hdroffset = pef_hdroffset + sizeof ih;
if (ih.Machine == 0x014C) {
if (ih.Machine == 0x014C || ih.Machine == 0x01C0) {
IMAGE_OPTIONAL_HEADER32 oh;
sec_hdroffset = opt_hdroffset + sizeof oh;
if (!read_mem(fd, opt_hdroffset, &oh, sizeof oh))
@ -1724,7 +1642,7 @@ static int get_dllexports(int fd, char **pp)
if (IMAGE_DIRECTORY_ENTRY_EXPORT >= oh.NumberOfRvaAndSizes)
goto the_end_0;
addr = oh.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
} else if (ih.Machine == 0x8664 || ih.Machine == IMAGE_FILE_MACHINE_ARM64) {
} else if (ih.Machine == 0x8664 || ih.Machine == 0xAA64) {
IMAGE_OPTIONAL_HEADER64 oh;
sec_hdroffset = opt_hdroffset + sizeof oh;
if (!read_mem(fd, opt_hdroffset, &oh, sizeof oh))
@ -2209,19 +2127,9 @@ static void pe_set_options(TCCState * s1, struct pe_info *pe)
{
if (PE_DLL == pe->type) {
/* XXX: check if is correct for arm-pe target */
#if defined(TCC_TARGET_ARM64)
pe->imagebase = 0x180000000ULL;
#else
pe->imagebase = 0x10000000;
#endif
pe->imagebase = IMAGE_BASE_DLL;
} else {
#if defined(TCC_TARGET_ARM)
pe->imagebase = 0x00010000;
#elif defined(TCC_TARGET_ARM64)
pe->imagebase = 0x140000000ULL;
#else
pe->imagebase = 0x00400000;
#endif
pe->imagebase = IMAGE_BASE_EXE;
}
#if defined(TCC_TARGET_ARM)

View File

@ -108,6 +108,11 @@ static void win64_del_function_table(void *);
//#define CONFIG_SELINUX 1
#endif
/* use VirtualAlloc() instead of tcc_malloc() */
#if defined _WIN32 && !defined CONFIG_RUNMEM_VIRTUALALLOC
# define CONFIG_RUNMEM_VIRTUALALLOC 1
#endif
static int rt_mem(TCCState *s1, int size)
{
void *ptr;
@ -129,16 +134,14 @@ static int rt_mem(TCCState *s1, int size)
ptr_diff = (char*)prw - (char*)ptr; /* = size; */
//printf("map %p %p %p\n", ptr, prw, (void*)ptr_diff);
size *= 2;
#else
# ifdef _WIN32
/* Generated code is page-protected below; avoid changing CRT heap pages. */
#elif CONFIG_RUNMEM_VIRTUALALLOC
/* always page-aligned */
ptr = VirtualAlloc(NULL, size, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
# else
ptr = tcc_malloc(size += PAGESIZE); /* one extra page to align malloc memory */
# endif
#endif
if (!ptr)
return tcc_error_noabort("tccrun: could not allocate memory");
#else
ptr = tcc_malloc(size += PAGESIZE); /* one extra page to align malloc memory */
#endif
s1->run_ptr = ptr;
s1->run_size = size;
return ptr_diff;
@ -191,24 +194,18 @@ ST_FUNC void tcc_run_free(TCCState *s1)
if (NULL == ptr)
return;
st_unlink(s1);
#ifdef _WIN64
win64_del_function_table(s1->run_function_table);
#endif
size = s1->run_size;
#ifdef CONFIG_SELINUX
munmap(ptr, size);
#elif CONFIG_RUNMEM_VIRTUALALLOC
VirtualFree(ptr, size, MEM_RELEASE);
#else
# ifdef _WIN32
(void)size;
# ifdef _WIN64
win64_del_function_table(s1->run_function_table);
# endif
VirtualFree(ptr, 0, MEM_RELEASE);
# else
/* unprotect memory to make it usable for malloc again */
protect_pages((void*)PAGEALIGN(ptr), size - PAGESIZE, 2 /*rw*/);
# ifdef _WIN64
win64_del_function_table(s1->run_function_table);
# endif
tcc_free(ptr);
# endif
#endif
}
@ -312,7 +309,7 @@ static void cleanup_sections(TCCState *s1)
}
/* ------------------------------------------------------------- */
/* 0 = .text rwx other rw (memory >= 2 pages a 4096 bytes) */
/* 0 = .text rwx other rwx (memory >= 2 pages a 4096 bytes) */
/* 1 = .text rx other rw (memory >= 3 pages) */
/* 2 = .text rx .rdata ro .data/.bss rw (memory >= 4 pages) */
@ -506,14 +503,11 @@ static void *win64_add_function_table(TCCState *s1)
void *p = NULL;
if (s1->uw_pdata) {
p = (void*)s1->uw_pdata->sh_addr;
if (!RtlAddFunctionTable(
RtlAddFunctionTable(
(RUNTIME_FUNCTION*)p,
s1->uw_pdata->data_offset / sizeof (RUNTIME_FUNCTION),
s1->pe_imagebase
)) {
tcc_error_noabort("RtlAddFunctionTable failed");
p = NULL;
}
);
s1->uw_pdata = NULL;
}
return p;

View File

@ -19,9 +19,6 @@ ifeq (,$(filter i386 x86_64,$(ARCH)))
SKIP += 85_asm-outside-function.test # x86 asm
SKIP += 127_asm_goto.test # hardcodes x86 asm
endif
ifeq (,$(filter x86_64 riscv64 arm64 i386,$(ARCH)))
SKIP += 144_tls.test # TLS only implemented on these architectures so far
endif
ifeq ($(CONFIG_backtrace),no)
SKIP += 113_btdll.test
CONFIG_bcheck = no
@ -57,22 +54,23 @@ ifneq (,$(filter OpenBSD FreeBSD NetBSD,$(TARGETOS)))
SKIP += 114_bound_signal.test # libc problem signal/fork
SKIP += 116_bound_setjmp2.test # No TLS_FUNC/TLS_VAR in bcheck.c
endif
ifdef CONFIG_OSX
ifeq ($(CONFIG_OSX),yes)
SKIP += 144_tls.test # TLS runtime not supported on Mach-O
endif
ifeq (,$(filter arm64 aarch64,$(ARCH)))
ifeq (,$(filter i386 x86_64 riscv64 arm64,$(ARCH)))
SKIP += 144_tls.test # TLS only implemented on these architectures so far
endif
ifneq (-$(ARCH)-,-arm64-)
SKIP += 138_arm64_encoding.test
SKIP += 139_arm64_errors.test
SKIP += 140_arm64_extasm.test
endif
ifneq ($(CONFIG_WIN32),yes)
SKIP += 145_winarm64_interlocked.test
else ifeq (,$(filter arm64 aarch64,$(ARCH)))
SKIP += 145_winarm64_interlocked.test
endif
ifeq (,$(filter riscv64,$(ARCH)))
ifneq (-$(ARCH)-,-riscv64-)
SKIP += 141_riscv_asm.test # riscv64 asm
endif
ifneq (-$(ARCH)-$(CONFIG_WIN32)-,-arm64-yes-)
SKIP += 145_winarm64_interlocked.test
endif
# Some tests might need arguments
ARGS =