5 Commits

Author SHA1 Message Date
Stefan
ba0899d909 tccasm.c: Make .init and .fini sections executable
GAS selects default attributes for a section based on its name and makes
the sections .text, .init, .fini executable. The crti.s and crtn.s files
of musl rely on these defaults and don't set the "x" flag for the .init
and .fini sections. Unfortunately TCC does not care for .init and .fini
section defaults in assembler or C code. Fix this for assembler code.
2025-09-21 14:06:59 +02:00
Stefan
2f88764100 libtcc.c: Remove unused defines free and realloc
These defines are not used in the code below their definition. They are
defined in tcc.h as well.
2025-09-21 13:30:15 +02:00
Stefan
95d184cba1 i386-asm.c: Optional % for variables in specific registers
Handle 'register long r10 __asm__("%r10")' without %, too. Using GCC
the % is optional. The musl source code does not use the % prefix.
The GCC source code uses both variants.
2025-09-21 13:18:37 +02:00
Stefan
5aebf106e8 i386-asm.c: Use NB_ASM_REGS instead of 8
For x86_64 there are more than just 8 registers.
2025-09-21 12:21:27 +02:00
Stefan
9dc59f9c23 i386-asm.c: Do bit-check for OP_SEG in asm_opcode
Fix a bug with "call *%%gs:16", which sets the two flags OP_INDIR and
OP_SEG in pop->type.
2025-09-21 12:18:11 +02:00
3 changed files with 16 additions and 14 deletions

View File

@@ -722,7 +722,7 @@ ST_FUNC void asm_opcode(TCCState *s1, int opcode)
}
parse_operand(s1, pop);
if (tok == ':') {
if (pop->type != OP_SEG || seg_prefix)
if (!(pop->type & OP_SEG) || seg_prefix)
tcc_error("incorrect prefix");
seg_prefix = segment_prefixes[pop->reg];
next();
@@ -852,7 +852,7 @@ again:
if (opcode >= TOK_ASM_first && opcode <= TOK_ASM_last) {
int b;
b = op0_codes[opcode - TOK_ASM_first];
if (b & 0xff00)
if (b & 0xff00)
g(b >> 8);
g(b);
return;
@@ -1233,8 +1233,8 @@ static const char *skip_constraint_modifiers(const char *p)
return p;
}
/* If T (a token) is of the form "%reg" returns the register
number and type, otherwise return -1. */
/* If t (a token) is of the form "%reg" or "reg" return the register number and
type, otherwise return -1. With GCC the % is optional, too. */
ST_FUNC int asm_parse_regvar (int t)
{
const char *s;
@@ -1242,13 +1242,14 @@ ST_FUNC int asm_parse_regvar (int t)
if (t < TOK_IDENT || (t & SYM_FIELD))
return -1;
s = table_ident[t - TOK_IDENT]->str;
if (s[0] != '%')
return -1;
t = tok_alloc_const(s + 1);
if (s[0] == '%')
++s;
t = tok_alloc_const(s);
unget_tok(t);
/* Internally the % prefix is required. */
unget_tok('%');
parse_operand(tcc_state, &op);
/* Accept only integer regs for now. */
/* Accept only integer regs for now. */
if (op.type & OP_REG)
return op.reg;
else
@@ -1416,7 +1417,7 @@ ST_FUNC void asm_compute_constraints(ASMOperand *operands,
/* any general register */
if ((reg = op->reg) >= 0)
goto reg_found;
else for(reg = 0; reg < 8; reg++) {
else for(reg = 0; reg < NB_ASM_REGS; reg++) {
if (!is_reg_allocated(reg))
goto reg_found;
}
@@ -1451,7 +1452,7 @@ ST_FUNC void asm_compute_constraints(ASMOperand *operands,
if (j < nb_outputs || c == 'm') {
if ((op->vt->r & VT_VALMASK) == VT_LLOCAL) {
/* any general register */
for(reg = 0; reg < 8; reg++) {
for(reg = 0; reg < NB_ASM_REGS; reg++) {
if (!(regs_allocated[reg] & REG_IN_MASK))
goto reg_found1;
}
@@ -1484,7 +1485,7 @@ ST_FUNC void asm_compute_constraints(ASMOperand *operands,
if (op->reg >= 0 &&
(op->vt->r & VT_VALMASK) == VT_LLOCAL &&
!op->is_memory) {
for(reg = 0; reg < 8; reg++) {
for(reg = 0; reg < NB_ASM_REGS; reg++) {
if (!(regs_allocated[reg] & REG_OUT_MASK))
goto reg_found2;
}

View File

@@ -257,9 +257,6 @@ ST_FUNC void libc_free(void *ptr)
free(ptr);
}
#define free(p) use_tcc_free(p)
#define realloc(p, s) use_tcc_realloc(p, s)
/* global so that every tcc_alloc()/tcc_free() call doesn't need to be changed */
static void *(*reallocator)(void*, unsigned long) = default_reallocator;

View File

@@ -907,6 +907,10 @@ static void asm_parse_directive(TCCState *s1, int global)
sets alignment to PTR_SIZE. The assembler behaves different. */
if (old_nb_section != s1->nb_sections) {
cur_text_section->sh_addralign = 1;
/* Make .init and .fini sections executable by default.
GAS does so, too, and musl relies on it. */
if (!strcmp(sname, ".init") || !strcmp(sname, ".fini"))
flags |= SHF_EXECINSTR;
cur_text_section->sh_flags = flags;
}
}