Add bound checking to arm, arm64 and riscv64
Checked on:
- i386/x86_64 (linux/windows)
- arm/arm64 (rapberry pi)
- riscv64 (simulator)
Not tested for arm softfloat because raspberry pi does not support it.
Modifications:
Makefile:
  add arm-asm.c to arm64_FILES
  add riscv64-asm.c (new file) to riscv64_FILES
lib/Makefile:
  add fetch_and_add_arm.o(new file) to ARM_O
  add fetch_and_add_arm64.o(new file) to ARM64_O
  add fetch_and_add_riscv64.o(new file) to RISCV64_O
  add $(BCHECK_O) to OBJ-arm/OBJ-arm64/OBJ-riscv64
tcc.h:
  Enable CONFIG_TCC_BCHECK for arm32/arm64/riscv64
  Add arm-asm.c, riscv64-asm.c
tcctok.h:
  for arm use memmove4 instead of memcpy4
  for arm use memmove8 instead of memcpy8
tccgen.c:
  put_extern_sym2: for arm check memcpy/memmove/memset/memmove4/memmove8
                   only use alloca for i386/x86_64
  for arm use memmove4 instead of memcpy4
  for arm use memmove8 instead of memcpy8
  fix builtin_frame_address/builtin_return_address for arm/riscv64
tccrun.c:
  Add riscv64 support
  fix rt_getcontext/rt_get_caller_pc for arm
tccelf.c:
  tcc_load_dll: Print filename for bad architecture
libtcc.c:
  add arm-asm.c/riscv64-asm.c
tcc-doc.texi:
  Add arm, arm64, riscv64 support for bound checking
lib/bcheck.c:
  add __bound___aeabi_memcpy/__bound___aeabi_memmove
      __bound___aeabi_memmove4/__bound___aeabi_memmove8
      __bound___aeabi_memset for arm
  call fetch_and_add_arm/fetch_and_add_arm64/fetch_and_add_riscv64
  __bound_init: Fix type for start/end/ad
  __bound_malloc/__bound_memalign/__bound_realloc/__bound_calloc: Use size + 1
arm-gen.c:
  add bound checking code like i386/x86_64
  assign_regs: only malloc if nb_args != 0
  gen_opi/gen_opf: Fix reload problems
arm-link.c:
  relocate_plt: Fix address calculating
arm64-gen.c:
  add bound checking code like i386/x86_64
  load/store: remove VT_BOUNDED from sv->r
  arm64_hfa_aux/arm64_hfa_aux: Fix array code
  gfunc_prolog: only malloc if n != 0
arm64-link.c:
  code_reloc/gotplt_entry_type/relocate: add R_AARCH64_LDST64_ABS_LO12_NC
  relocate: Use addXXle instead of writeXXle
riscv64-gen.c:
  add bound checking code like i386/x86_64
  add NB_ASM_REGS/CONFIG_TCC_ASM
riscv64-link.c:
  relocate: Use addXXle instead of writeXXle
i386-gen.c/x86_64-gen.c
  gen_bounds_epilog: Fix code (unrelated)
tests/Makefile:
  add $(BTESTS) for arm/arm64/riscv64
tests/tests2/Makefile:
  Use 85 only on i386/x86_64 because of asm code
  Use 113 only on i386/x86_64 because of DLL code
  Add 112/114/115/116 for arm/arm64/riscv64
  Fix FILTER (failed on riscv64)
tests/boundtest.c:
  Only use alloca for i386/x86_64
			
			
This commit is contained in:
		
							parent
							
								
									9eef33993a
								
							
						
					
					
						commit
						0b8ee7364a
					
				
					 25 changed files with 865 additions and 77 deletions
				
			
		
							
								
								
									
										4
									
								
								Makefile
									
										
									
									
									
								
							
							
						
						
									
										4
									
								
								Makefile
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -176,9 +176,9 @@ arm-fpa-ld_FILES  = $(arm_FILES)
 | 
			
		|||
arm-vfp_FILES     = $(arm_FILES)
 | 
			
		||||
arm-eabi_FILES    = $(arm_FILES)
 | 
			
		||||
arm-eabihf_FILES  = $(arm_FILES)
 | 
			
		||||
arm64_FILES = $(CORE_FILES) arm64-gen.c arm64-link.c
 | 
			
		||||
arm64_FILES = $(CORE_FILES) arm64-gen.c arm64-link.c arm-asm.c
 | 
			
		||||
c67_FILES = $(CORE_FILES) c67-gen.c c67-link.c tcccoff.c
 | 
			
		||||
riscv64_FILES = $(CORE_FILES) riscv64-gen.c riscv64-link.c
 | 
			
		||||
riscv64_FILES = $(CORE_FILES) riscv64-gen.c riscv64-link.c riscv64-asm.c
 | 
			
		||||
 | 
			
		||||
# libtcc sources
 | 
			
		||||
LIBTCC_SRC = $(filter-out tcc.c tcctools.c,$(filter %.c,$($T_FILES)))
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										218
									
								
								arm-gen.c
									
										
									
									
									
								
							
							
						
						
									
										218
									
								
								arm-gen.c
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -158,6 +158,12 @@ ST_DATA const int reg_classes[NB_REGS] = {
 | 
			
		|||
static int func_sub_sp_offset, last_itod_magic;
 | 
			
		||||
static int leaffunc;
 | 
			
		||||
 | 
			
		||||
#if defined(CONFIG_TCC_BCHECK)
 | 
			
		||||
static addr_t func_bound_offset;
 | 
			
		||||
static unsigned long func_bound_ind;
 | 
			
		||||
static int func_bound_add_epilog;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if defined(TCC_ARM_EABI) && defined(TCC_ARM_VFP)
 | 
			
		||||
static CType float_type, double_type, func_float_type, func_double_type;
 | 
			
		||||
ST_FUNC void arm_init(struct TCCState *s)
 | 
			
		||||
| 
						 | 
				
			
			@ -193,11 +199,17 @@ ST_FUNC void arm_init(struct TCCState *s)
 | 
			
		|||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#define CHECK_R(r) ((r) >= TREG_R0 && (r) <= TREG_LR)
 | 
			
		||||
 | 
			
		||||
static int two2mask(int a,int b) {
 | 
			
		||||
  if (!CHECK_R(a) || !CHECK_R(b))
 | 
			
		||||
    tcc_error("compiler error! registers %i,%i is not valid",a,b);
 | 
			
		||||
  return (reg_classes[a]|reg_classes[b])&~(RC_INT|RC_FLOAT);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int regmask(int r) {
 | 
			
		||||
  if (!CHECK_R(r))
 | 
			
		||||
    tcc_error("compiler error! register %i is not valid",r);
 | 
			
		||||
  return reg_classes[r]&~(RC_INT|RC_FLOAT);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -751,6 +763,14 @@ static void gcall_or_jmp(int is_jmp)
 | 
			
		|||
			greloc(cur_text_section, vtop->sym, ind, R_ARM_ABS32);
 | 
			
		||||
			o(vtop->c.i);
 | 
			
		||||
		}
 | 
			
		||||
#ifdef CONFIG_TCC_BCHECK
 | 
			
		||||
                if (tcc_state->do_bounds_check &&
 | 
			
		||||
                    (vtop->sym->v == TOK_setjmp ||
 | 
			
		||||
                     vtop->sym->v == TOK__setjmp ||
 | 
			
		||||
                     vtop->sym->v == TOK_sigsetjmp ||
 | 
			
		||||
                     vtop->sym->v == TOK___sigsetjmp))
 | 
			
		||||
                    func_bound_add_epilog = 1;
 | 
			
		||||
#endif
 | 
			
		||||
	}else{
 | 
			
		||||
		if(!is_jmp)
 | 
			
		||||
			o(0xE28FE004); // add lr,pc,#4
 | 
			
		||||
| 
						 | 
				
			
			@ -759,6 +779,9 @@ static void gcall_or_jmp(int is_jmp)
 | 
			
		|||
	}
 | 
			
		||||
  } else {
 | 
			
		||||
    /* otherwise, indirect call */
 | 
			
		||||
#ifdef CONFIG_TCC_BCHECK
 | 
			
		||||
    vtop->r &= ~VT_MUSTBOUND;
 | 
			
		||||
#endif
 | 
			
		||||
    r = gv(RC_INT);
 | 
			
		||||
    if(!is_jmp)
 | 
			
		||||
      o(0xE1A0E00F);       // mov lr,pc
 | 
			
		||||
| 
						 | 
				
			
			@ -766,6 +789,121 @@ static void gcall_or_jmp(int is_jmp)
 | 
			
		|||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if defined(CONFIG_TCC_BCHECK)
 | 
			
		||||
 | 
			
		||||
static void gen_bounds_call(int v)
 | 
			
		||||
{
 | 
			
		||||
    Sym *sym = external_global_sym(v, &func_old_type);
 | 
			
		||||
 | 
			
		||||
    greloc(cur_text_section, sym, ind, R_ARM_PC24);
 | 
			
		||||
    o(0xebfffffe);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* generate a bounded pointer addition */
 | 
			
		||||
ST_FUNC void gen_bounded_ptr_add(void)
 | 
			
		||||
{
 | 
			
		||||
    vpush_global_sym(&func_old_type, TOK___bound_ptr_add);
 | 
			
		||||
    vrott(3);
 | 
			
		||||
    gfunc_call(2);
 | 
			
		||||
    vpushi(0);
 | 
			
		||||
    /* returned pointer is in REG_IRET */
 | 
			
		||||
    vtop->r = REG_IRET | VT_BOUNDED;
 | 
			
		||||
    if (nocode_wanted)
 | 
			
		||||
        return;
 | 
			
		||||
    /* relocation offset of the bounding function call point */
 | 
			
		||||
    vtop->c.i = (cur_text_section->reloc->data_offset - sizeof(Elf32_Rel));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* patch pointer addition in vtop so that pointer dereferencing is
 | 
			
		||||
   also tested */
 | 
			
		||||
ST_FUNC void gen_bounded_ptr_deref(void)
 | 
			
		||||
{
 | 
			
		||||
    addr_t func;
 | 
			
		||||
    int size, align;
 | 
			
		||||
    Elf32_Rel *rel;
 | 
			
		||||
    Sym *sym;
 | 
			
		||||
 | 
			
		||||
    if (nocode_wanted)
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
    size = type_size(&vtop->type, &align);
 | 
			
		||||
    switch(size) {
 | 
			
		||||
    case  1: func = TOK___bound_ptr_indir1; break;
 | 
			
		||||
    case  2: func = TOK___bound_ptr_indir2; break;
 | 
			
		||||
    case  4: func = TOK___bound_ptr_indir4; break;
 | 
			
		||||
    case  8: func = TOK___bound_ptr_indir8; break;
 | 
			
		||||
    case 12: func = TOK___bound_ptr_indir12; break;
 | 
			
		||||
    case 16: func = TOK___bound_ptr_indir16; break;
 | 
			
		||||
    default:
 | 
			
		||||
        /* may happen with struct member access */
 | 
			
		||||
        return;
 | 
			
		||||
        //tcc_error("unhandled size when dereferencing bounded pointer");
 | 
			
		||||
        //func = 0;
 | 
			
		||||
        //break;
 | 
			
		||||
    }
 | 
			
		||||
    sym = external_global_sym(func, &func_old_type);
 | 
			
		||||
    if (!sym->c)
 | 
			
		||||
        put_extern_sym(sym, NULL, 0, 0);
 | 
			
		||||
    /* patch relocation */
 | 
			
		||||
    /* XXX: find a better solution ? */
 | 
			
		||||
    rel = (Elf32_Rel *)(cur_text_section->reloc->data + vtop->c.i);
 | 
			
		||||
    rel->r_info = ELF32_R_INFO(sym->c, ELF32_R_TYPE(rel->r_info));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void gen_bounds_prolog(void)
 | 
			
		||||
{
 | 
			
		||||
    /* leave some room for bound checking code */
 | 
			
		||||
    func_bound_offset = lbounds_section->data_offset;
 | 
			
		||||
    func_bound_ind = ind;
 | 
			
		||||
    func_bound_add_epilog = 0;
 | 
			
		||||
    o(0xe1a00000);  /* ld r0,lbounds_section->data_offset */
 | 
			
		||||
    o(0xe1a00000);
 | 
			
		||||
    o(0xe1a00000);
 | 
			
		||||
    o(0xe1a00000);  /* call __bound_local_new */
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void gen_bounds_epilog(void)
 | 
			
		||||
{
 | 
			
		||||
    addr_t saved_ind;
 | 
			
		||||
    addr_t *bounds_ptr;
 | 
			
		||||
    Sym *sym_data;
 | 
			
		||||
    int offset_modified = func_bound_offset != lbounds_section->data_offset;
 | 
			
		||||
 | 
			
		||||
    if (!offset_modified && !func_bound_add_epilog)
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
    /* add end of table info */
 | 
			
		||||
    bounds_ptr = section_ptr_add(lbounds_section, sizeof(addr_t));
 | 
			
		||||
    *bounds_ptr = 0;
 | 
			
		||||
 | 
			
		||||
    sym_data = get_sym_ref(&char_pointer_type, lbounds_section,
 | 
			
		||||
                           func_bound_offset, lbounds_section->data_offset);
 | 
			
		||||
 | 
			
		||||
    /* generate bound local allocation */
 | 
			
		||||
    if (offset_modified) {
 | 
			
		||||
        saved_ind = ind;
 | 
			
		||||
        ind = func_bound_ind;
 | 
			
		||||
        o(0xe59f0000);  /* ldr r0, [pc] */
 | 
			
		||||
        o(0xea000000);  /* b $+4 */
 | 
			
		||||
        greloc(cur_text_section, sym_data, ind, R_ARM_ABS32);
 | 
			
		||||
        o(0x00000000);  /* lbounds_section->data_offset */
 | 
			
		||||
        gen_bounds_call(TOK___bound_local_new);
 | 
			
		||||
        ind = saved_ind;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* generate bound check local freeing */
 | 
			
		||||
    o(0xe92d0003);  /* push {r0,r1} */
 | 
			
		||||
    o(0xed2d0b02);  /* vpush {d0} */
 | 
			
		||||
    o(0xe59f0000);  /* ldr r0, [pc] */
 | 
			
		||||
    o(0xea000000);  /* b $+4 */
 | 
			
		||||
    greloc(cur_text_section, sym_data, ind, R_ARM_ABS32);
 | 
			
		||||
    o(0x00000000);  /* lbounds_section->data_offset */
 | 
			
		||||
    gen_bounds_call(TOK___bound_local_delete);
 | 
			
		||||
    o(0xecbd0b02); /* vpop {d0} */
 | 
			
		||||
    o(0xe8bd0003); /* pop {r0,r1} */
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
static int unalias_ldbl(int btype)
 | 
			
		||||
{
 | 
			
		||||
#if LDOUBLE_SIZE == 8
 | 
			
		||||
| 
						 | 
				
			
			@ -956,7 +1094,7 @@ static int assign_regs(int nb_args, int float_abi, struct plan *plan, int *todo)
 | 
			
		|||
 | 
			
		||||
  ncrn = nsaa = 0;
 | 
			
		||||
  *todo = 0;
 | 
			
		||||
  plan->pplans = tcc_malloc(nb_args * sizeof(*plan->pplans));
 | 
			
		||||
  plan->pplans = nb_args ? tcc_malloc(nb_args * sizeof(*plan->pplans)) : NULL;
 | 
			
		||||
  memset(plan->clsplans, 0, sizeof(plan->clsplans));
 | 
			
		||||
  for(i = nb_args; i-- ;) {
 | 
			
		||||
    int j, start_vfpreg = 0;
 | 
			
		||||
| 
						 | 
				
			
			@ -1215,10 +1353,16 @@ void gfunc_call(int nb_args)
 | 
			
		|||
  int def_float_abi = float_abi;
 | 
			
		||||
  int todo;
 | 
			
		||||
  struct plan plan;
 | 
			
		||||
 | 
			
		||||
#ifdef TCC_ARM_EABI
 | 
			
		||||
  int variadic;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef CONFIG_TCC_BCHECK
 | 
			
		||||
  if (tcc_state->do_bounds_check)
 | 
			
		||||
    gbound_args(nb_args);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef TCC_ARM_EABI
 | 
			
		||||
  if (float_abi == ARM_HARD_FLOAT) {
 | 
			
		||||
    variadic = (vtop[-nb_args].type.ref->f.func_type == FUNC_ELLIPSIS);
 | 
			
		||||
    if (variadic || floats_in_core_regs(&vtop[-nb_args]))
 | 
			
		||||
| 
						 | 
				
			
			@ -1367,6 +1511,10 @@ from_stack:
 | 
			
		|||
  last_itod_magic=0;
 | 
			
		||||
  leaffunc = 1;
 | 
			
		||||
  loc = 0;
 | 
			
		||||
#ifdef CONFIG_TCC_BCHECK
 | 
			
		||||
  if (tcc_state->do_bounds_check)
 | 
			
		||||
    gen_bounds_prolog();
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* generate function epilog */
 | 
			
		||||
| 
						 | 
				
			
			@ -1374,6 +1522,11 @@ void gfunc_epilog(void)
 | 
			
		|||
{
 | 
			
		||||
  uint32_t x;
 | 
			
		||||
  int diff;
 | 
			
		||||
 | 
			
		||||
#ifdef CONFIG_TCC_BCHECK
 | 
			
		||||
  if (tcc_state->do_bounds_check)
 | 
			
		||||
    gen_bounds_epilog();
 | 
			
		||||
#endif
 | 
			
		||||
  /* Copy float return value to core register if base standard is used and
 | 
			
		||||
     float computation is made with VFP */
 | 
			
		||||
#if defined(TCC_ARM_EABI) && defined(TCC_ARM_VFP)
 | 
			
		||||
| 
						 | 
				
			
			@ -1582,10 +1735,10 @@ void gen_opi(int op)
 | 
			
		|||
      vswap();
 | 
			
		||||
      c=intr(gv(RC_INT));
 | 
			
		||||
      vswap();
 | 
			
		||||
      opc=0xE0000000|(opc<<20)|(c<<16);
 | 
			
		||||
      opc=0xE0000000|(opc<<20);
 | 
			
		||||
      if((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {
 | 
			
		||||
	uint32_t x;
 | 
			
		||||
	x=stuff_const(opc|0x2000000,vtop->c.i);
 | 
			
		||||
	x=stuff_const(opc|0x2000000|(c<<16),vtop->c.i);
 | 
			
		||||
	if(x) {
 | 
			
		||||
	  r=intr(vtop[-1].r=get_reg_ex(RC_INT,regmask(vtop[-1].r)));
 | 
			
		||||
	  o(x|(r<<12));
 | 
			
		||||
| 
						 | 
				
			
			@ -1593,8 +1746,13 @@ void gen_opi(int op)
 | 
			
		|||
	}
 | 
			
		||||
      }
 | 
			
		||||
      fr=intr(gv(RC_INT));
 | 
			
		||||
      if ((vtop[-1].r & VT_VALMASK) >= VT_CONST) {
 | 
			
		||||
        vswap();
 | 
			
		||||
        c=intr(gv(RC_INT));
 | 
			
		||||
        vswap();
 | 
			
		||||
      }
 | 
			
		||||
      r=intr(vtop[-1].r=get_reg_ex(RC_INT,two2mask(vtop->r,vtop[-1].r)));
 | 
			
		||||
      o(opc|(r<<12)|fr);
 | 
			
		||||
      o(opc|(c<<16)|(r<<12)|fr);
 | 
			
		||||
done:
 | 
			
		||||
      vtop--;
 | 
			
		||||
      if (op >= TOK_ULT && op <= TOK_GT)
 | 
			
		||||
| 
						 | 
				
			
			@ -1608,15 +1766,19 @@ done:
 | 
			
		|||
      vswap();
 | 
			
		||||
      r=intr(gv(RC_INT));
 | 
			
		||||
      vswap();
 | 
			
		||||
      opc|=r;
 | 
			
		||||
      if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {
 | 
			
		||||
	fr=intr(vtop[-1].r=get_reg_ex(RC_INT,regmask(vtop[-1].r)));
 | 
			
		||||
	c = vtop->c.i & 0x1f;
 | 
			
		||||
	o(opc|(c<<7)|(fr<<12));
 | 
			
		||||
	o(opc|r|(c<<7)|(fr<<12));
 | 
			
		||||
      } else {
 | 
			
		||||
        fr=intr(gv(RC_INT));
 | 
			
		||||
        if ((vtop[-1].r & VT_VALMASK) >= VT_CONST) {
 | 
			
		||||
          vswap();
 | 
			
		||||
          r=intr(gv(RC_INT));
 | 
			
		||||
          vswap();
 | 
			
		||||
        }
 | 
			
		||||
	c=intr(vtop[-1].r=get_reg_ex(RC_INT,two2mask(vtop->r,vtop[-1].r)));
 | 
			
		||||
	o(opc|(c<<12)|(fr<<8)|0x10);
 | 
			
		||||
	o(opc|r|(c<<12)|(fr<<8)|0x10);
 | 
			
		||||
      }
 | 
			
		||||
      vtop--;
 | 
			
		||||
      break;
 | 
			
		||||
| 
						 | 
				
			
			@ -1701,9 +1863,9 @@ void gen_opf(int op)
 | 
			
		|||
        vtop--;
 | 
			
		||||
        o(x|0x10000|(vfpr(gv(RC_FLOAT))<<12)); /* fcmp(e)X -> fcmp(e)zX */
 | 
			
		||||
      } else {
 | 
			
		||||
        x|=vfpr(gv(RC_FLOAT));
 | 
			
		||||
        vswap();
 | 
			
		||||
        o(x|(vfpr(gv(RC_FLOAT))<<12));
 | 
			
		||||
        gv2(RC_FLOAT,RC_FLOAT);
 | 
			
		||||
        x|=vfpr(vtop[0].r);
 | 
			
		||||
        o(x|(vfpr(vtop[-1].r) << 12));
 | 
			
		||||
        vtop--;
 | 
			
		||||
      }
 | 
			
		||||
      o(0xEEF1FA10); /* fmstat */
 | 
			
		||||
| 
						 | 
				
			
			@ -1726,6 +1888,12 @@ void gen_opf(int op)
 | 
			
		|||
    r2=gv(RC_FLOAT);
 | 
			
		||||
    x|=vfpr(r2)<<16;
 | 
			
		||||
    r|=regmask(r2);
 | 
			
		||||
    if ((vtop[-1].r & VT_VALMASK) >= VT_CONST) {
 | 
			
		||||
      vswap();
 | 
			
		||||
      r=gv(RC_FLOAT);
 | 
			
		||||
      vswap();
 | 
			
		||||
      x=(x&~0xf)|vfpr(r);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  vtop->r=get_reg_ex(RC_FLOAT,r);
 | 
			
		||||
  if(!fneg)
 | 
			
		||||
| 
						 | 
				
			
			@ -1808,6 +1976,11 @@ void gen_opf(int op)
 | 
			
		|||
	r2=c2&0xf;
 | 
			
		||||
      } else {
 | 
			
		||||
	r2=fpr(gv(RC_FLOAT));
 | 
			
		||||
        if ((vtop[-1].r & VT_VALMASK) >= VT_CONST) {
 | 
			
		||||
          vswap();
 | 
			
		||||
          r=fpr(gv(RC_FLOAT));
 | 
			
		||||
          vswap();
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
      break;
 | 
			
		||||
    case '-':
 | 
			
		||||
| 
						 | 
				
			
			@ -1829,6 +2002,11 @@ void gen_opf(int op)
 | 
			
		|||
	r=fpr(gv(RC_FLOAT));
 | 
			
		||||
	vswap();
 | 
			
		||||
	r2=fpr(gv(RC_FLOAT));
 | 
			
		||||
        if ((vtop[-1].r & VT_VALMASK) >= VT_CONST) {
 | 
			
		||||
          vswap();
 | 
			
		||||
          r=fpr(gv(RC_FLOAT));
 | 
			
		||||
          vswap();
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
      break;
 | 
			
		||||
    case '*':
 | 
			
		||||
| 
						 | 
				
			
			@ -1841,8 +2019,14 @@ void gen_opf(int op)
 | 
			
		|||
      vswap();
 | 
			
		||||
      if(c2 && c2<=0xf)
 | 
			
		||||
	r2=c2;
 | 
			
		||||
      else
 | 
			
		||||
      else {
 | 
			
		||||
	r2=fpr(gv(RC_FLOAT));
 | 
			
		||||
        if ((vtop[-1].r & VT_VALMASK) >= VT_CONST) {
 | 
			
		||||
          vswap();
 | 
			
		||||
          r=fpr(gv(RC_FLOAT));
 | 
			
		||||
          vswap();
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
      x|=0x100000; // muf
 | 
			
		||||
      break;
 | 
			
		||||
    case '/':
 | 
			
		||||
| 
						 | 
				
			
			@ -1863,6 +2047,11 @@ void gen_opf(int op)
 | 
			
		|||
	r=fpr(gv(RC_FLOAT));
 | 
			
		||||
	vswap();
 | 
			
		||||
	r2=fpr(gv(RC_FLOAT));
 | 
			
		||||
        if ((vtop[-1].r & VT_VALMASK) >= VT_CONST) {
 | 
			
		||||
          vswap();
 | 
			
		||||
          r=fpr(gv(RC_FLOAT));
 | 
			
		||||
          vswap();
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
      break;
 | 
			
		||||
    default:
 | 
			
		||||
| 
						 | 
				
			
			@ -1915,6 +2104,11 @@ void gen_opf(int op)
 | 
			
		|||
	  r2=c2&0xf;
 | 
			
		||||
	} else {
 | 
			
		||||
	  r2=fpr(gv(RC_FLOAT));
 | 
			
		||||
          if ((vtop[-1].r & VT_VALMASK) >= VT_CONST) {
 | 
			
		||||
            vswap();
 | 
			
		||||
            r=fpr(gv(RC_FLOAT));
 | 
			
		||||
            vswap();
 | 
			
		||||
          }
 | 
			
		||||
	}
 | 
			
		||||
        --vtop;
 | 
			
		||||
        vset_VT_CMP(op);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -155,7 +155,7 @@ ST_FUNC void relocate_plt(TCCState *s1)
 | 
			
		|||
        while (p < p_end) {
 | 
			
		||||
            if (read32le(p) == 0x46c04778) /* PLT Thumb stub present */
 | 
			
		||||
                p += 4;
 | 
			
		||||
            add32le(p + 12, x + s1->plt->data - p);
 | 
			
		||||
            add32le(p + 12, x + (s1->plt->data - p));
 | 
			
		||||
            p += 16;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										171
									
								
								arm64-gen.c
									
										
									
									
									
								
							
							
						
						
									
										171
									
								
								arm64-gen.c
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -81,6 +81,12 @@ ST_DATA const int reg_classes[NB_REGS] = {
 | 
			
		|||
  RC_FLOAT | RC_F(7)
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#if defined(CONFIG_TCC_BCHECK)
 | 
			
		||||
static addr_t func_bound_offset;
 | 
			
		||||
static unsigned long func_bound_ind;
 | 
			
		||||
static int func_bound_add_epilog;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#define IS_FREG(x) ((x) >= TREG_F(0))
 | 
			
		||||
 | 
			
		||||
static uint32_t intr(int r)
 | 
			
		||||
| 
						 | 
				
			
			@ -454,7 +460,7 @@ static void arm64_load_cmp(int r, SValue *sv);
 | 
			
		|||
ST_FUNC void load(int r, SValue *sv)
 | 
			
		||||
{
 | 
			
		||||
    int svtt = sv->type.t;
 | 
			
		||||
    int svr = sv->r;
 | 
			
		||||
    int svr = sv->r & ~VT_BOUNDED;
 | 
			
		||||
    int svrv = svr & VT_VALMASK;
 | 
			
		||||
    uint64_t svcul = (uint32_t)sv->c.i;
 | 
			
		||||
    svcul = svcul >> 31 & 1 ? svcul - ((uint64_t)1 << 32) : svcul;
 | 
			
		||||
| 
						 | 
				
			
			@ -554,7 +560,7 @@ ST_FUNC void load(int r, SValue *sv)
 | 
			
		|||
ST_FUNC void store(int r, SValue *sv)
 | 
			
		||||
{
 | 
			
		||||
    int svtt = sv->type.t;
 | 
			
		||||
    int svr = sv->r;
 | 
			
		||||
    int svr = sv->r & ~VT_BOUNDED;
 | 
			
		||||
    int svrv = svr & VT_VALMASK;
 | 
			
		||||
    uint64_t svcul = (uint32_t)sv->c.i;
 | 
			
		||||
    svcul = svcul >> 31 & 1 ? svcul - ((uint64_t)1 << 32) : svcul;
 | 
			
		||||
| 
						 | 
				
			
			@ -594,11 +600,147 @@ static void arm64_gen_bl_or_b(int b)
 | 
			
		|||
        assert(!b);
 | 
			
		||||
	greloca(cur_text_section, vtop->sym, ind, R_AARCH64_CALL26, 0);
 | 
			
		||||
	o(0x94000000); // bl .
 | 
			
		||||
#ifdef CONFIG_TCC_BCHECK
 | 
			
		||||
        if (tcc_state->do_bounds_check &&
 | 
			
		||||
            (vtop->sym->v == TOK_setjmp ||
 | 
			
		||||
             vtop->sym->v == TOK__setjmp ||
 | 
			
		||||
             vtop->sym->v == TOK_sigsetjmp ||
 | 
			
		||||
             vtop->sym->v == TOK___sigsetjmp))
 | 
			
		||||
            func_bound_add_epilog = 1;
 | 
			
		||||
#endif
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    else {
 | 
			
		||||
#ifdef CONFIG_TCC_BCHECK
 | 
			
		||||
        vtop->r &= ~VT_MUSTBOUND;
 | 
			
		||||
#endif
 | 
			
		||||
        o(0xd61f0000 | (uint32_t)!b << 21 | intr(gv(RC_R30)) << 5); // br/blr
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if defined(CONFIG_TCC_BCHECK)
 | 
			
		||||
 | 
			
		||||
static void gen_bounds_call(int v)
 | 
			
		||||
{
 | 
			
		||||
    Sym *sym = external_global_sym(v, &func_old_type);
 | 
			
		||||
 | 
			
		||||
    greloca(cur_text_section, sym, ind, R_AARCH64_CALL26, 0);
 | 
			
		||||
    o(0x94000000); // bl
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* generate a bounded pointer addition */
 | 
			
		||||
ST_FUNC void gen_bounded_ptr_add(void)
 | 
			
		||||
{
 | 
			
		||||
    vpush_global_sym(&func_old_type, TOK___bound_ptr_add);
 | 
			
		||||
    vrott(3);
 | 
			
		||||
    gfunc_call(2);
 | 
			
		||||
    vpushi(0);
 | 
			
		||||
    /* returned pointer is in REG_IRET */
 | 
			
		||||
    vtop->r = REG_IRET | VT_BOUNDED;
 | 
			
		||||
    if (nocode_wanted)
 | 
			
		||||
        return;
 | 
			
		||||
    /* relocation offset of the bounding function call point */
 | 
			
		||||
    vtop->c.i = (cur_text_section->reloc->data_offset - sizeof(ElfW(Rela)));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* patch pointer addition in vtop so that pointer dereferencing is
 | 
			
		||||
   also tested */
 | 
			
		||||
ST_FUNC void gen_bounded_ptr_deref(void)
 | 
			
		||||
{
 | 
			
		||||
    addr_t func;
 | 
			
		||||
    int size, align;
 | 
			
		||||
    ElfW(Rela) *rel;
 | 
			
		||||
    Sym *sym;
 | 
			
		||||
 | 
			
		||||
    if (nocode_wanted)
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
    size = type_size(&vtop->type, &align);
 | 
			
		||||
    switch(size) {
 | 
			
		||||
    case  1: func = TOK___bound_ptr_indir1; break;
 | 
			
		||||
    case  2: func = TOK___bound_ptr_indir2; break;
 | 
			
		||||
    case  4: func = TOK___bound_ptr_indir4; break;
 | 
			
		||||
    case  8: func = TOK___bound_ptr_indir8; break;
 | 
			
		||||
    case 12: func = TOK___bound_ptr_indir12; break;
 | 
			
		||||
    case 16: func = TOK___bound_ptr_indir16; break;
 | 
			
		||||
    default:
 | 
			
		||||
        /* may happen with struct member access */
 | 
			
		||||
        return;
 | 
			
		||||
        //tcc_error("unhandled size when dereferencing bounded pointer");
 | 
			
		||||
        //func = 0;
 | 
			
		||||
        //break;
 | 
			
		||||
    }
 | 
			
		||||
    sym = external_global_sym(func, &func_old_type);
 | 
			
		||||
    if (!sym->c)
 | 
			
		||||
        put_extern_sym(sym, NULL, 0, 0);
 | 
			
		||||
    /* patch relocation */
 | 
			
		||||
    /* XXX: find a better solution ? */
 | 
			
		||||
    rel = (ElfW(Rela) *)(cur_text_section->reloc->data + vtop->c.i);
 | 
			
		||||
    rel->r_info = ELF64_R_INFO(sym->c, ELF64_R_TYPE(rel->r_info));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void gen_bounds_prolog(void)
 | 
			
		||||
{
 | 
			
		||||
    /* leave some room for bound checking code */
 | 
			
		||||
    func_bound_offset = lbounds_section->data_offset;
 | 
			
		||||
    func_bound_ind = ind;
 | 
			
		||||
    func_bound_add_epilog = 0;
 | 
			
		||||
    o(0xd503201f);  /* nop -> mov x0,#0,lsl #0, lbound section pointer */
 | 
			
		||||
    o(0xd503201f);
 | 
			
		||||
    o(0xd503201f);
 | 
			
		||||
    o(0xd503201f);
 | 
			
		||||
    o(0xd503201f);  /* nop -> call __bound_local_new */
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void gen_bounds_epilog(void)
 | 
			
		||||
{
 | 
			
		||||
    addr_t saved_ind;
 | 
			
		||||
    addr_t *bounds_ptr;
 | 
			
		||||
    Sym *sym_data;
 | 
			
		||||
    int offset_modified = func_bound_offset != lbounds_section->data_offset;
 | 
			
		||||
 | 
			
		||||
    if (!offset_modified && !func_bound_add_epilog)
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
    /* add end of table info */
 | 
			
		||||
    bounds_ptr = section_ptr_add(lbounds_section, sizeof(addr_t));
 | 
			
		||||
    *bounds_ptr = 0;
 | 
			
		||||
 | 
			
		||||
    sym_data = get_sym_ref(&char_pointer_type, lbounds_section,
 | 
			
		||||
                           func_bound_offset, lbounds_section->data_offset);
 | 
			
		||||
 | 
			
		||||
    /* generate bound local allocation */
 | 
			
		||||
    if (offset_modified) {
 | 
			
		||||
        saved_ind = ind;
 | 
			
		||||
        ind = func_bound_ind;
 | 
			
		||||
        greloca(cur_text_section, sym_data, ind, R_AARCH64_MOVW_UABS_G0_NC, 0);
 | 
			
		||||
        o(0xd2800000);  /* mov x0,#0,lsl #0, lbound section pointer */
 | 
			
		||||
        greloca(cur_text_section, sym_data, ind, R_AARCH64_MOVW_UABS_G1_NC, 0);
 | 
			
		||||
        o(0xf2a00000);  /* movk x0,#0,lsl #16 */
 | 
			
		||||
        greloca(cur_text_section, sym_data, ind, R_AARCH64_MOVW_UABS_G2_NC, 0);
 | 
			
		||||
        o(0xf2c00000);  /* movk x0,#0,lsl #32 */
 | 
			
		||||
        greloca(cur_text_section, sym_data, ind, R_AARCH64_MOVW_UABS_G3, 0);
 | 
			
		||||
        o(0xf2e00000);  /* movk x0,#0,lsl #48 */
 | 
			
		||||
        gen_bounds_call(TOK___bound_local_new);
 | 
			
		||||
        ind = saved_ind;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* generate bound check local freeing */
 | 
			
		||||
    o(0xf81f0fe0); /* str x0, [sp, #-16]! */
 | 
			
		||||
    o(0x3c9f0fe0); /* str q0, [sp, #-16]! */
 | 
			
		||||
    greloca(cur_text_section, sym_data, ind, R_AARCH64_MOVW_UABS_G0_NC, 0);
 | 
			
		||||
    o(0xd2800000); // mov x0,#0,lsl #0
 | 
			
		||||
    greloca(cur_text_section, sym_data, ind, R_AARCH64_MOVW_UABS_G1_NC, 0);
 | 
			
		||||
    o(0xf2a00000); // movk x0,#0,lsl #16
 | 
			
		||||
    greloca(cur_text_section, sym_data, ind, R_AARCH64_MOVW_UABS_G2_NC, 0);
 | 
			
		||||
    o(0xf2c00000); // movk x0,#0,lsl #32
 | 
			
		||||
    greloca(cur_text_section, sym_data, ind, R_AARCH64_MOVW_UABS_G3, 0);
 | 
			
		||||
    o(0xf2e00000); // movk x0,#0,lsl #48
 | 
			
		||||
    gen_bounds_call(TOK___bound_local_delete);
 | 
			
		||||
    o(0x3cc107e0); /* ldr q0, [sp], #16 */
 | 
			
		||||
    o(0xf84107e0); /* ldr x0, [sp], #16 */
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
static int arm64_hfa_aux(CType *type, int *fsize, int num)
 | 
			
		||||
{
 | 
			
		||||
    if (is_float(type->t)) {
 | 
			
		||||
| 
						 | 
				
			
			@ -642,7 +784,7 @@ static int arm64_hfa_aux(CType *type, int *fsize, int num)
 | 
			
		|||
            return num;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    else if (type->t & VT_ARRAY) {
 | 
			
		||||
    else if ((type->t & VT_ARRAY) && ((type->t & VT_BTYPE) != VT_PTR)) {
 | 
			
		||||
        int num1;
 | 
			
		||||
        if (!type->ref->c)
 | 
			
		||||
            return num;
 | 
			
		||||
| 
						 | 
				
			
			@ -659,7 +801,8 @@ static int arm64_hfa_aux(CType *type, int *fsize, int num)
 | 
			
		|||
 | 
			
		||||
static int arm64_hfa(CType *type, int *fsize)
 | 
			
		||||
{
 | 
			
		||||
    if ((type->t & VT_BTYPE) == VT_STRUCT || (type->t & VT_ARRAY)) {
 | 
			
		||||
    if ((type->t & VT_BTYPE) == VT_STRUCT ||
 | 
			
		||||
        ((type->t & VT_ARRAY) && ((type->t & VT_BTYPE) != VT_PTR))) {
 | 
			
		||||
        int sz = 0;
 | 
			
		||||
        int n = arm64_hfa_aux(type, &sz, 0);
 | 
			
		||||
        if (0 < n && n <= 4) {
 | 
			
		||||
| 
						 | 
				
			
			@ -839,6 +982,11 @@ ST_FUNC void gfunc_call(int nb_args)
 | 
			
		|||
    unsigned long stack;
 | 
			
		||||
    int i;
 | 
			
		||||
 | 
			
		||||
#ifdef CONFIG_TCC_BCHECK
 | 
			
		||||
    if (tcc_state->do_bounds_check)
 | 
			
		||||
        gbound_args(nb_args);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    return_type = &vtop[-nb_args].type.ref->type;
 | 
			
		||||
    if ((return_type->t & VT_BTYPE) == VT_STRUCT)
 | 
			
		||||
        --nb_args;
 | 
			
		||||
| 
						 | 
				
			
			@ -1014,8 +1162,8 @@ ST_FUNC void gfunc_prolog(Sym *func_sym)
 | 
			
		|||
 | 
			
		||||
    for (sym = func_type->ref; sym; sym = sym->next)
 | 
			
		||||
        ++n;
 | 
			
		||||
    t = tcc_malloc(n * sizeof(*t));
 | 
			
		||||
    a = tcc_malloc(n * sizeof(*a));
 | 
			
		||||
    t = n ? tcc_malloc(n * sizeof(*t)) : NULL;
 | 
			
		||||
    a = n ? tcc_malloc(n * sizeof(*a)) : NULL;
 | 
			
		||||
 | 
			
		||||
    for (sym = func_type->ref; sym; sym = sym->next)
 | 
			
		||||
        t[i++] = &sym->type;
 | 
			
		||||
| 
						 | 
				
			
			@ -1076,6 +1224,10 @@ ST_FUNC void gfunc_prolog(Sym *func_sym)
 | 
			
		|||
    o(0xd503201f); // nop
 | 
			
		||||
    o(0xd503201f); // nop
 | 
			
		||||
    loc = 0;
 | 
			
		||||
#ifdef CONFIG_TCC_BCHECK
 | 
			
		||||
    if (tcc_state->do_bounds_check)
 | 
			
		||||
        gen_bounds_prolog();
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ST_FUNC void gen_va_start(void)
 | 
			
		||||
| 
						 | 
				
			
			@ -1246,6 +1398,11 @@ ST_FUNC void gfunc_return(CType *func_type)
 | 
			
		|||
 | 
			
		||||
ST_FUNC void gfunc_epilog(void)
 | 
			
		||||
{
 | 
			
		||||
#ifdef CONFIG_TCC_BCHECK
 | 
			
		||||
    if (tcc_state->do_bounds_check)
 | 
			
		||||
        gen_bounds_epilog();
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    if (loc) {
 | 
			
		||||
        // Insert instructions to subtract size of stack frame from SP.
 | 
			
		||||
        unsigned char *ptr = cur_text_section->data + arm64_func_sub_sp_offset;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										10
									
								
								arm64-link.c
									
										
									
									
									
								
							
							
						
						
									
										10
									
								
								arm64-link.c
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -37,6 +37,7 @@ int code_reloc (int reloc_type)
 | 
			
		|||
        case R_AARCH64_ADD_ABS_LO12_NC:
 | 
			
		||||
        case R_AARCH64_ADR_GOT_PAGE:
 | 
			
		||||
        case R_AARCH64_LD64_GOT_LO12_NC:
 | 
			
		||||
        case R_AARCH64_LDST64_ABS_LO12_NC:
 | 
			
		||||
        case R_AARCH64_GLOB_DAT:
 | 
			
		||||
        case R_AARCH64_COPY:
 | 
			
		||||
            return 0;
 | 
			
		||||
| 
						 | 
				
			
			@ -62,6 +63,7 @@ int gotplt_entry_type (int reloc_type)
 | 
			
		|||
        case R_AARCH64_MOVW_UABS_G3:
 | 
			
		||||
        case R_AARCH64_ADR_PREL_PG_HI21:
 | 
			
		||||
        case R_AARCH64_ADD_ABS_LO12_NC:
 | 
			
		||||
        case R_AARCH64_LDST64_ABS_LO12_NC:
 | 
			
		||||
        case R_AARCH64_GLOB_DAT:
 | 
			
		||||
        case R_AARCH64_JUMP_SLOT:
 | 
			
		||||
        case R_AARCH64_COPY:
 | 
			
		||||
| 
						 | 
				
			
			@ -157,10 +159,10 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t
 | 
			
		|||
 | 
			
		||||
    switch(type) {
 | 
			
		||||
        case R_AARCH64_ABS64:
 | 
			
		||||
            write64le(ptr, val);
 | 
			
		||||
            add64le(ptr, val);
 | 
			
		||||
            return;
 | 
			
		||||
        case R_AARCH64_ABS32:
 | 
			
		||||
            write32le(ptr, val);
 | 
			
		||||
            add32le(ptr, val);
 | 
			
		||||
            return;
 | 
			
		||||
	case R_AARCH64_PREL32:
 | 
			
		||||
	    write32le(ptr, val - addr);
 | 
			
		||||
| 
						 | 
				
			
			@ -193,6 +195,10 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t
 | 
			
		|||
            write32le(ptr, ((read32le(ptr) & 0xffc003ff) |
 | 
			
		||||
                            (val & 0xfff) << 10));
 | 
			
		||||
            return;
 | 
			
		||||
        case R_AARCH64_LDST64_ABS_LO12_NC:
 | 
			
		||||
            write32le(ptr, ((read32le(ptr) & 0xffc003ff) |
 | 
			
		||||
                            (val & 0xff8) << 7));
 | 
			
		||||
            return;
 | 
			
		||||
        case R_AARCH64_JUMP26:
 | 
			
		||||
        case R_AARCH64_CALL26:
 | 
			
		||||
#ifdef DEBUG_RELOC
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1089,8 +1089,9 @@ static void gen_bounds_epilog(void)
 | 
			
		|||
    addr_t saved_ind;
 | 
			
		||||
    addr_t *bounds_ptr;
 | 
			
		||||
    Sym *sym_data;
 | 
			
		||||
    int offset_modified = func_bound_offset != lbounds_section->data_offset;
 | 
			
		||||
 | 
			
		||||
    if (func_bound_offset == lbounds_section->data_offset && !func_bound_add_epilog)
 | 
			
		||||
    if (!offset_modified && !func_bound_add_epilog)
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
    /* add end of table info */
 | 
			
		||||
| 
						 | 
				
			
			@ -1101,7 +1102,7 @@ static void gen_bounds_epilog(void)
 | 
			
		|||
                           func_bound_offset, lbounds_section->data_offset);
 | 
			
		||||
 | 
			
		||||
    /* generate bound local allocation */
 | 
			
		||||
    if (func_bound_offset != lbounds_section->data_offset) {
 | 
			
		||||
    if (offset_modified) {
 | 
			
		||||
        saved_ind = ind;
 | 
			
		||||
        ind = func_bound_ind;
 | 
			
		||||
        greloc(cur_text_section, sym_data, ind + 1, R_386_32);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										12
									
								
								lib/Makefile
									
										
									
									
									
								
							
							
						
						
									
										12
									
								
								lib/Makefile
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -43,9 +43,9 @@ endif
 | 
			
		|||
 | 
			
		||||
I386_O = libtcc1.o alloca86.o alloca86-bt.o $(BT_O)
 | 
			
		||||
X86_64_O = libtcc1.o alloca86_64.o alloca86_64-bt.o $(BT_O)
 | 
			
		||||
ARM_O = libtcc1.o armeabi.o alloca-arm.o armflush.o $(BT_O)
 | 
			
		||||
ARM64_O = lib-arm64.o $(BT_O)
 | 
			
		||||
RISCV64_O = lib-arm64.o $(BT_O)
 | 
			
		||||
ARM_O = libtcc1.o armeabi.o alloca-arm.o armflush.o fetch_and_add_arm.o $(BT_O)
 | 
			
		||||
ARM64_O = lib-arm64.o fetch_and_add_arm64.o $(BT_O)
 | 
			
		||||
RISCV64_O = lib-arm64.o fetch_and_add_riscv64.o $(BT_O)
 | 
			
		||||
WIN_O = crt1.o crt1w.o wincrt1.o wincrt1w.o dllcrt1.o dllmain.o
 | 
			
		||||
 | 
			
		||||
OBJ-i386 = $(I386_O) $(BCHECK_O) $(DSO_O)
 | 
			
		||||
| 
						 | 
				
			
			@ -53,15 +53,15 @@ OBJ-x86_64 = $(X86_64_O) va_list.o $(BCHECK_O) $(DSO_O)
 | 
			
		|||
OBJ-x86_64-osx = $(X86_64_O) va_list.o
 | 
			
		||||
OBJ-i386-win32 = $(I386_O) chkstk.o $(B_O) $(WIN_O)
 | 
			
		||||
OBJ-x86_64-win32 = $(X86_64_O) chkstk.o $(B_O) $(WIN_O)
 | 
			
		||||
OBJ-arm64 = $(ARM64_O) $(DSO_O)
 | 
			
		||||
OBJ-arm = $(ARM_O) $(DSO_O)
 | 
			
		||||
OBJ-arm64 = $(ARM64_O) $(BCHECK_O) $(DSO_O)
 | 
			
		||||
OBJ-arm = $(ARM_O) $(BCHECK_O) $(DSO_O)
 | 
			
		||||
OBJ-arm-fpa = $(ARM_O) $(DSO_O)
 | 
			
		||||
OBJ-arm-fpa-ld = $(ARM_O) $(DSO_O)
 | 
			
		||||
OBJ-arm-vfp = $(ARM_O) $(DSO_O)
 | 
			
		||||
OBJ-arm-eabi = $(ARM_O) $(DSO_O)
 | 
			
		||||
OBJ-arm-eabihf = $(ARM_O) $(DSO_O)
 | 
			
		||||
OBJ-arm-wince = $(ARM_O) $(WIN_O)
 | 
			
		||||
OBJ-riscv64 = $(RISCV64_O) $(DSO_O)
 | 
			
		||||
OBJ-riscv64 = $(RISCV64_O) $(BCHECK_O) $(DSO_O)
 | 
			
		||||
 | 
			
		||||
OBJ-extra = $(filter $(B_O),$(OBJ-$T))
 | 
			
		||||
OBJ-libtcc1 = $(addprefix $(X),$(filter-out $(OBJ-extra),$(OBJ-$T)))
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										97
									
								
								lib/bcheck.c
									
										
									
									
									
								
							
							
						
						
									
										97
									
								
								lib/bcheck.c
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -163,7 +163,7 @@ typedef struct alloca_list_struct {
 | 
			
		|||
#if defined(_WIN32)
 | 
			
		||||
#define BOUND_TID_TYPE   DWORD
 | 
			
		||||
#define BOUND_GET_TID    GetCurrentThreadId()
 | 
			
		||||
#elif defined(__i386__) || defined(__x86_64__)
 | 
			
		||||
#elif defined(__i386__) || defined(__x86_64__) || defined(__arm__) || defined(__aarch64__) || defined(__riscv)
 | 
			
		||||
#define BOUND_TID_TYPE   pid_t
 | 
			
		||||
#define BOUND_GET_TID    syscall (SYS_gettid)
 | 
			
		||||
#else
 | 
			
		||||
| 
						 | 
				
			
			@ -223,6 +223,19 @@ DLL_EXPORT char *__bound_strcat(char *dest, const char *src);
 | 
			
		|||
DLL_EXPORT char *__bound_strchr(const char *string, int ch);
 | 
			
		||||
DLL_EXPORT char *__bound_strdup(const char *s);
 | 
			
		||||
 | 
			
		||||
#if defined(__arm__)
 | 
			
		||||
DLL_EXPORT void *__bound___aeabi_memcpy(void *dst, const void *src, size_t size);
 | 
			
		||||
DLL_EXPORT void *__bound___aeabi_memmove(void *dst, const void *src, size_t size);
 | 
			
		||||
DLL_EXPORT void *__bound___aeabi_memmove4(void *dst, const void *src, size_t size);
 | 
			
		||||
DLL_EXPORT void *__bound___aeabi_memmove8(void *dst, const void *src, size_t size);
 | 
			
		||||
DLL_EXPORT void *__bound___aeabi_memset(void *dst, int c, size_t size);
 | 
			
		||||
DLL_EXPORT void *__aeabi_memcpy(void *dst, const void *src, size_t size);
 | 
			
		||||
DLL_EXPORT void *__aeabi_memmove(void *dst, const void *src, size_t size);
 | 
			
		||||
DLL_EXPORT void *__aeabi_memmove4(void *dst, const void *src, size_t size);
 | 
			
		||||
DLL_EXPORT void *__aeabi_memmove8(void *dst, const void *src, size_t size);
 | 
			
		||||
DLL_EXPORT void *__aeabi_memset(void *dst, int c, size_t size);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if MALLOC_REDIR
 | 
			
		||||
#define BOUND_MALLOC(a)          malloc_redir(a)
 | 
			
		||||
#define BOUND_MEMALIGN(a,b)      memalign_redir(a,b)
 | 
			
		||||
| 
						 | 
				
			
			@ -320,6 +333,15 @@ static void fetch_and_add(signed char* variable, signed char value)
 | 
			
		|||
        : // No input-only
 | 
			
		||||
        : "memory"
 | 
			
		||||
      );
 | 
			
		||||
#elif defined __arm__
 | 
			
		||||
      extern fetch_and_add_arm(signed char* variable, signed char value);
 | 
			
		||||
      fetch_and_add_arm(variable, value);
 | 
			
		||||
#elif defined __aarch64__
 | 
			
		||||
      extern fetch_and_add_arm64(signed char* variable, signed char value);
 | 
			
		||||
      fetch_and_add_arm64(variable, value);
 | 
			
		||||
#elif defined __riscv
 | 
			
		||||
      extern fetch_and_add_riscv64(signed char* variable, signed char value);
 | 
			
		||||
      fetch_and_add_riscv64(variable, value);
 | 
			
		||||
#else
 | 
			
		||||
      *variable += value;
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			@ -814,10 +836,10 @@ void __bound_init(size_t *p)
 | 
			
		|||
    {
 | 
			
		||||
        FILE *fp;
 | 
			
		||||
        unsigned char found;
 | 
			
		||||
        unsigned long long start;
 | 
			
		||||
        unsigned long long end;
 | 
			
		||||
        unsigned long long ad =
 | 
			
		||||
            (unsigned long long) __builtin_return_address(0);
 | 
			
		||||
        unsigned long start;
 | 
			
		||||
        unsigned long end;
 | 
			
		||||
        unsigned long ad =
 | 
			
		||||
            (unsigned long) __builtin_return_address(0);
 | 
			
		||||
        char line[1000];
 | 
			
		||||
 | 
			
		||||
        /* Display exec name. Usefull when a lot of code is compiled with tcc */
 | 
			
		||||
| 
						 | 
				
			
			@ -835,7 +857,7 @@ void __bound_init(size_t *p)
 | 
			
		|||
        fp = fopen ("/proc/self/maps", "r");
 | 
			
		||||
        if (fp) {
 | 
			
		||||
            while (fgets (line, sizeof(line), fp)) {
 | 
			
		||||
                if (sscanf (line, "%Lx-%Lx", &start, &end) == 2 &&
 | 
			
		||||
                if (sscanf (line, "%lx-%lx", &start, &end) == 2 &&
 | 
			
		||||
                            ad >= start && ad < end) {
 | 
			
		||||
                    found = 1;
 | 
			
		||||
                    break;
 | 
			
		||||
| 
						 | 
				
			
			@ -1099,7 +1121,7 @@ void *__bound_malloc(size_t size, const void *caller)
 | 
			
		|||
        INCR_COUNT(bound_malloc_count);
 | 
			
		||||
 | 
			
		||||
        if (ptr) {
 | 
			
		||||
            tree = splay_insert ((size_t) ptr, size, tree);
 | 
			
		||||
            tree = splay_insert ((size_t) ptr, size ? size : size + 1, tree);
 | 
			
		||||
            if (tree && tree->start == (size_t) ptr)
 | 
			
		||||
                tree->type = TCC_TYPE_MALLOC;
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			@ -1138,7 +1160,7 @@ void *__bound_memalign(size_t size, size_t align, const void *caller)
 | 
			
		|||
        INCR_COUNT(bound_memalign_count);
 | 
			
		||||
 | 
			
		||||
        if (ptr) {
 | 
			
		||||
            tree = splay_insert((size_t) ptr, size, tree);
 | 
			
		||||
            tree = splay_insert((size_t) ptr, size ? size : size + 1, tree);
 | 
			
		||||
            if (tree && tree->start == (size_t) ptr)
 | 
			
		||||
                tree->type = TCC_TYPE_MEMALIGN;
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			@ -1205,7 +1227,7 @@ void *__bound_realloc(void *ptr, size_t size, const void *caller)
 | 
			
		|||
        return NULL;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    new_ptr = BOUND_REALLOC (ptr, size);
 | 
			
		||||
    new_ptr = BOUND_REALLOC (ptr, size + 1);
 | 
			
		||||
    dprintf(stderr, "%s, %s(): %p, 0x%lx\n",
 | 
			
		||||
            __FILE__, __FUNCTION__, new_ptr, (unsigned long)size);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1216,7 +1238,7 @@ void *__bound_realloc(void *ptr, size_t size, const void *caller)
 | 
			
		|||
        if (ptr)
 | 
			
		||||
            tree = splay_delete ((size_t) ptr, tree);
 | 
			
		||||
        if (new_ptr) {
 | 
			
		||||
            tree = splay_insert ((size_t) new_ptr, size, tree);
 | 
			
		||||
            tree = splay_insert ((size_t) new_ptr, size ? size : size + 1, tree);
 | 
			
		||||
            if (tree && tree->start == (size_t) new_ptr)
 | 
			
		||||
                tree->type = TCC_TYPE_REALLOC;
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			@ -1259,7 +1281,7 @@ void *__bound_calloc(size_t nmemb, size_t size)
 | 
			
		|||
        if (no_checking == 0) {
 | 
			
		||||
            WAIT_SEM ();
 | 
			
		||||
            INCR_COUNT(bound_calloc_count);
 | 
			
		||||
            tree = splay_insert ((size_t) ptr, size, tree);
 | 
			
		||||
            tree = splay_insert ((size_t) ptr, size ? size : size + 1, tree);
 | 
			
		||||
            if (tree && tree->start == (size_t) ptr)
 | 
			
		||||
                tree->type = TCC_TYPE_CALLOC;
 | 
			
		||||
            POST_SEM ();
 | 
			
		||||
| 
						 | 
				
			
			@ -1387,6 +1409,59 @@ void *__bound_memset(void *s, int c, size_t n)
 | 
			
		|||
    return memset(s, c, n);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if defined(__arm__)
 | 
			
		||||
void *__bound___aeabi_memcpy(void *dest, const void *src, size_t n)
 | 
			
		||||
{
 | 
			
		||||
    dprintf(stderr, "%s, %s(): %p, %p, 0x%lx\n",
 | 
			
		||||
            __FILE__, __FUNCTION__, dest, src, (unsigned long)n);
 | 
			
		||||
    INCR_COUNT(bound_mempcy_count);
 | 
			
		||||
    __bound_check(dest, n, "memcpy dest");
 | 
			
		||||
    __bound_check(src, n, "memcpy src");
 | 
			
		||||
    if (check_overlap(dest, n, src, n, "memcpy"))
 | 
			
		||||
        return dest;
 | 
			
		||||
    return __aeabi_memcpy(dest, src, n);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void *__bound___aeabi_memmove(void *dest, const void *src, size_t n)
 | 
			
		||||
{
 | 
			
		||||
    dprintf(stderr, "%s, %s(): %p, %p, 0x%lx\n",
 | 
			
		||||
            __FILE__, __FUNCTION__, dest, src, (unsigned long)n);
 | 
			
		||||
    INCR_COUNT(bound_memmove_count);
 | 
			
		||||
    __bound_check(dest, n, "memmove dest");
 | 
			
		||||
    __bound_check(src, n, "memmove src");
 | 
			
		||||
    return __aeabi_memmove(dest, src, n);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void *__bound___aeabi_memmove4(void *dest, const void *src, size_t n)
 | 
			
		||||
{
 | 
			
		||||
    dprintf(stderr, "%s, %s(): %p, %p, 0x%lx\n",
 | 
			
		||||
            __FILE__, __FUNCTION__, dest, src, (unsigned long)n);
 | 
			
		||||
    INCR_COUNT(bound_memmove_count);
 | 
			
		||||
    __bound_check(dest, n, "memmove dest");
 | 
			
		||||
    __bound_check(src, n, "memmove src");
 | 
			
		||||
    return __aeabi_memmove4(dest, src, n);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void *__bound___aeabi_memmove8(void *dest, const void *src, size_t n)
 | 
			
		||||
{
 | 
			
		||||
    dprintf(stderr, "%s, %s(): %p, %p, 0x%lx\n",
 | 
			
		||||
            __FILE__, __FUNCTION__, dest, src, (unsigned long)n);
 | 
			
		||||
    INCR_COUNT(bound_memmove_count);
 | 
			
		||||
    __bound_check(dest, n, "memmove dest");
 | 
			
		||||
    __bound_check(src, n, "memmove src");
 | 
			
		||||
    return __aeabi_memmove8(dest, src, n);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void *__bound___aeabi_memset(void *s, int c, size_t n)
 | 
			
		||||
{
 | 
			
		||||
    dprintf(stderr, "%s, %s(): %p, %d, 0x%lx\n",
 | 
			
		||||
            __FILE__, __FUNCTION__, s, c, (unsigned long)n);
 | 
			
		||||
    INCR_COUNT(bound_memset_count);
 | 
			
		||||
    __bound_check(s, n, "memset");
 | 
			
		||||
    return __aeabi_memset(s, c, n);
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
int __bound_strlen(const char *s)
 | 
			
		||||
{
 | 
			
		||||
    const char *p = s;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										16
									
								
								lib/fetch_and_add_arm.S
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								lib/fetch_and_add_arm.S
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,16 @@
 | 
			
		|||
        .text
 | 
			
		||||
        .align  2
 | 
			
		||||
        .global fetch_and_add_arm
 | 
			
		||||
        .type   fetch_and_add_arm, %function
 | 
			
		||||
fetch_and_add_arm:
 | 
			
		||||
        .int 0xee070fba #      mcr     15, 0, r0, cr7, cr10, {5}
 | 
			
		||||
        .int 0xe1903f9f #      ldrex   r3, [r0]
 | 
			
		||||
        .int 0xe2833001 #      add     r3, r3, #1
 | 
			
		||||
        .int 0xe1802f93 #      strex   r2, r3, [r0]
 | 
			
		||||
        .int 0xe3520000 #      cmp     r2, #0
 | 
			
		||||
        .int 0x1afffffa #      bne     4 <fetch_and_add_arm+0x4>
 | 
			
		||||
        .int 0xee070fba #      mcr     15, 0, r0, cr7, cr10, {5}
 | 
			
		||||
        .int 0xe1a00003 #      mov     r0, r3
 | 
			
		||||
        .int 0xe12fff1e #      bx      lr
 | 
			
		||||
 | 
			
		||||
	.size   fetch_and_add_arm, .-fetch_and_add_arm
 | 
			
		||||
							
								
								
									
										14
									
								
								lib/fetch_and_add_arm64.S
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								lib/fetch_and_add_arm64.S
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,14 @@
 | 
			
		|||
        .text
 | 
			
		||||
        .align  2
 | 
			
		||||
        .global fetch_and_add_arm64
 | 
			
		||||
        .type   fetch_and_add_arm64, %function
 | 
			
		||||
fetch_and_add_arm64:
 | 
			
		||||
        .int 0x885f7c01 #      ldxr    w1, [x0]
 | 
			
		||||
        .int 0x11000421 #      add     w1, w1, #0x1
 | 
			
		||||
        .int 0x8802fc01 #      stlxr   w2, w1, [x0]
 | 
			
		||||
        .int 0x35ffffa2 #      cbnz    w2, 0 <fetch_and_add_arm64>
 | 
			
		||||
        .int 0xd5033bbf #      dmb     ish
 | 
			
		||||
        .int 0x2a0103e0 #      mov     w0, w1
 | 
			
		||||
        .int 0xd65f03c0 #      ret
 | 
			
		||||
 | 
			
		||||
	.size   fetch_and_add_arm64, .-fetch_and_add_arm64
 | 
			
		||||
							
								
								
									
										12
									
								
								lib/fetch_and_add_riscv64.S
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								lib/fetch_and_add_riscv64.S
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,12 @@
 | 
			
		|||
        .text
 | 
			
		||||
        .align  2
 | 
			
		||||
        .global fetch_and_add_riscv64
 | 
			
		||||
        .type   fetch_and_add_riscv64, %function
 | 
			
		||||
fetch_and_add_riscv64:
 | 
			
		||||
        .short 0x4705     #              li      a4,1
 | 
			
		||||
        .int   0x0f50000f #              fence   iorw,ow
 | 
			
		||||
        .int   0x04e527af #              amoadd.w.aq     a5,a4,(a0)
 | 
			
		||||
        .int   0x0017851b #              addiw   a0,a5,1
 | 
			
		||||
        .short 0x8082     #              ret
 | 
			
		||||
 | 
			
		||||
        .size   fetch_and_add_riscv64, .-fetch_and_add_riscv64
 | 
			
		||||
							
								
								
									
										2
									
								
								libtcc.c
									
										
									
									
									
								
							
							
						
						
									
										2
									
								
								libtcc.c
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -34,6 +34,7 @@
 | 
			
		|||
#elif defined(TCC_TARGET_ARM64)
 | 
			
		||||
#include "arm64-gen.c"
 | 
			
		||||
#include "arm64-link.c"
 | 
			
		||||
#include "arm-asm.c"
 | 
			
		||||
#elif defined(TCC_TARGET_C67)
 | 
			
		||||
#include "c67-gen.c"
 | 
			
		||||
#include "c67-link.c"
 | 
			
		||||
| 
						 | 
				
			
			@ -45,6 +46,7 @@
 | 
			
		|||
#elif defined(TCC_TARGET_RISCV64)
 | 
			
		||||
#include "riscv64-gen.c"
 | 
			
		||||
#include "riscv64-link.c"
 | 
			
		||||
#include "riscv64-asm.c"
 | 
			
		||||
#else
 | 
			
		||||
#error unknown target
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										94
									
								
								riscv64-asm.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										94
									
								
								riscv64-asm.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,94 @@
 | 
			
		|||
/*************************************************************/
 | 
			
		||||
/*
 | 
			
		||||
 *  RISCV64 dummy assembler for TCC
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifdef TARGET_DEFS_ONLY
 | 
			
		||||
 | 
			
		||||
#define CONFIG_TCC_ASM
 | 
			
		||||
#define NB_ASM_REGS 32
 | 
			
		||||
 | 
			
		||||
ST_FUNC void g(int c);
 | 
			
		||||
ST_FUNC void gen_le16(int c);
 | 
			
		||||
ST_FUNC void gen_le32(int c);
 | 
			
		||||
 | 
			
		||||
/*************************************************************/
 | 
			
		||||
#else
 | 
			
		||||
/*************************************************************/
 | 
			
		||||
#define USING_GLOBALS
 | 
			
		||||
#include "tcc.h"
 | 
			
		||||
 | 
			
		||||
static void asm_error(void)
 | 
			
		||||
{
 | 
			
		||||
    tcc_error("RISCV64 asm not implemented.");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* XXX: make it faster ? */
 | 
			
		||||
ST_FUNC void g(int c)
 | 
			
		||||
{
 | 
			
		||||
    int ind1;
 | 
			
		||||
    if (nocode_wanted)
 | 
			
		||||
        return;
 | 
			
		||||
    ind1 = ind + 1;
 | 
			
		||||
    if (ind1 > cur_text_section->data_allocated)
 | 
			
		||||
        section_realloc(cur_text_section, ind1);
 | 
			
		||||
    cur_text_section->data[ind] = c;
 | 
			
		||||
    ind = ind1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ST_FUNC void gen_le16 (int i)
 | 
			
		||||
{
 | 
			
		||||
    g(i);
 | 
			
		||||
    g(i>>8);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ST_FUNC void gen_le32 (int i)
 | 
			
		||||
{
 | 
			
		||||
    gen_le16(i);
 | 
			
		||||
    gen_le16(i>>16);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ST_FUNC void gen_expr32(ExprValue *pe)
 | 
			
		||||
{
 | 
			
		||||
    gen_le32(pe->v);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ST_FUNC void asm_opcode(TCCState *s1, int opcode)
 | 
			
		||||
{
 | 
			
		||||
    asm_error();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ST_FUNC void subst_asm_operand(CString *add_str, SValue *sv, int modifier)
 | 
			
		||||
{
 | 
			
		||||
    asm_error();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* generate prolog and epilog code for asm statement */
 | 
			
		||||
ST_FUNC void asm_gen_code(ASMOperand *operands, int nb_operands,
 | 
			
		||||
                         int nb_outputs, int is_output,
 | 
			
		||||
                         uint8_t *clobber_regs,
 | 
			
		||||
                         int out_reg)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ST_FUNC void asm_compute_constraints(ASMOperand *operands,
 | 
			
		||||
                                    int nb_operands, int nb_outputs,
 | 
			
		||||
                                    const uint8_t *clobber_regs,
 | 
			
		||||
                                    int *pout_reg)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ST_FUNC void asm_clobber(uint8_t *clobber_regs, const char *str)
 | 
			
		||||
{
 | 
			
		||||
    asm_error();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ST_FUNC int asm_parse_regvar (int t)
 | 
			
		||||
{
 | 
			
		||||
    asm_error();
 | 
			
		||||
    return -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*************************************************************/
 | 
			
		||||
#endif /* ndef TARGET_DEFS_ONLY */
 | 
			
		||||
							
								
								
									
										155
									
								
								riscv64-gen.c
									
										
									
									
									
								
							
							
						
						
									
										155
									
								
								riscv64-gen.c
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -2,6 +2,8 @@
 | 
			
		|||
 | 
			
		||||
// Number of registers available to allocator:
 | 
			
		||||
#define NB_REGS 19 // x10-x17 aka a0-a7, f10-f17 aka fa0-fa7, xxx, ra, sp
 | 
			
		||||
#define NB_ASM_REGS 32
 | 
			
		||||
#define CONFIG_TCC_ASM
 | 
			
		||||
 | 
			
		||||
#define TREG_R(x) (x) // x = 0..7
 | 
			
		||||
#define TREG_F(x) (x + 8) // x = 0..7
 | 
			
		||||
| 
						 | 
				
			
			@ -61,6 +63,12 @@ ST_DATA const int reg_classes[NB_REGS] = {
 | 
			
		|||
  1 << TREG_SP
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#if defined(CONFIG_TCC_BCHECK)
 | 
			
		||||
static addr_t func_bound_offset;
 | 
			
		||||
static unsigned long func_bound_ind;
 | 
			
		||||
static int func_bound_add_epilog;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
static int ireg(int r)
 | 
			
		||||
{
 | 
			
		||||
    if (r == TREG_RA)
 | 
			
		||||
| 
						 | 
				
			
			@ -377,6 +385,14 @@ static void gcall_or_jmp(int docall)
 | 
			
		|||
                R_RISCV_CALL_PLT, (int)vtop->c.i);
 | 
			
		||||
        o(0x17 | (tr << 7));   // auipc TR, 0 %call(func)
 | 
			
		||||
        EI(0x67, 0, tr, tr, 0);// jalr  TR, r(TR)
 | 
			
		||||
#ifdef CONFIG_TCC_BCHECK
 | 
			
		||||
        if (tcc_state->do_bounds_check &&
 | 
			
		||||
            (vtop->sym->v == TOK_setjmp ||
 | 
			
		||||
             vtop->sym->v == TOK__setjmp ||
 | 
			
		||||
             vtop->sym->v == TOK_sigsetjmp ||
 | 
			
		||||
             vtop->sym->v == TOK___sigsetjmp))
 | 
			
		||||
            func_bound_add_epilog = 1;
 | 
			
		||||
#endif
 | 
			
		||||
    } else if (vtop->r < VT_CONST) {
 | 
			
		||||
        int r = ireg(vtop->r);
 | 
			
		||||
        EI(0x67, 0, tr, r, 0);      // jalr TR, 0(R)
 | 
			
		||||
| 
						 | 
				
			
			@ -388,6 +404,130 @@ static void gcall_or_jmp(int docall)
 | 
			
		|||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if defined(CONFIG_TCC_BCHECK)
 | 
			
		||||
 | 
			
		||||
static void gen_bounds_call(int v)
 | 
			
		||||
{
 | 
			
		||||
    Sym *sym = external_global_sym(v, &func_old_type);
 | 
			
		||||
 | 
			
		||||
    greloca(cur_text_section, sym, ind, R_RISCV_CALL_PLT, 0);
 | 
			
		||||
    o(0x17 | (1 << 7));   // auipc TR, 0 %call(func)
 | 
			
		||||
    EI(0x67, 0, 1, 1, 0); // jalr  TR, r(TR)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* generate a bounded pointer addition */
 | 
			
		||||
ST_FUNC void gen_bounded_ptr_add(void)
 | 
			
		||||
{
 | 
			
		||||
    vpush_global_sym(&func_old_type, TOK___bound_ptr_add);
 | 
			
		||||
    vrott(3);
 | 
			
		||||
    gfunc_call(2);
 | 
			
		||||
    vpushi(0);
 | 
			
		||||
    /* returned pointer is in REG_IRET */
 | 
			
		||||
    vtop->r = REG_IRET | VT_BOUNDED;
 | 
			
		||||
    if (nocode_wanted)
 | 
			
		||||
        return;
 | 
			
		||||
    /* relocation offset of the bounding function call point */
 | 
			
		||||
    vtop->c.i = (cur_text_section->reloc->data_offset - sizeof(ElfW(Rela)));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* patch pointer addition in vtop so that pointer dereferencing is
 | 
			
		||||
   also tested */
 | 
			
		||||
ST_FUNC void gen_bounded_ptr_deref(void)
 | 
			
		||||
{
 | 
			
		||||
    addr_t func;
 | 
			
		||||
    int size, align;
 | 
			
		||||
    ElfW(Rela) *rel;
 | 
			
		||||
    Sym *sym;
 | 
			
		||||
 | 
			
		||||
    if (nocode_wanted)
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
    size = type_size(&vtop->type, &align);
 | 
			
		||||
    switch(size) {
 | 
			
		||||
    case  1: func = TOK___bound_ptr_indir1; break;
 | 
			
		||||
    case  2: func = TOK___bound_ptr_indir2; break;
 | 
			
		||||
    case  4: func = TOK___bound_ptr_indir4; break;
 | 
			
		||||
    case  8: func = TOK___bound_ptr_indir8; break;
 | 
			
		||||
    case 12: func = TOK___bound_ptr_indir12; break;
 | 
			
		||||
    case 16: func = TOK___bound_ptr_indir16; break;
 | 
			
		||||
    default:
 | 
			
		||||
        /* may happen with struct member access */
 | 
			
		||||
        return;
 | 
			
		||||
        //tcc_error("unhandled size when dereferencing bounded pointer");
 | 
			
		||||
        //func = 0;
 | 
			
		||||
        //break;
 | 
			
		||||
    }
 | 
			
		||||
    sym = external_global_sym(func, &func_old_type);
 | 
			
		||||
    if (!sym->c)
 | 
			
		||||
        put_extern_sym(sym, NULL, 0, 0);
 | 
			
		||||
    /* patch relocation */
 | 
			
		||||
    /* XXX: find a better solution ? */
 | 
			
		||||
    rel = (ElfW(Rela) *)(cur_text_section->reloc->data + vtop->c.i);
 | 
			
		||||
    rel->r_info = ELF64_R_INFO(sym->c, ELF64_R_TYPE(rel->r_info));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void gen_bounds_prolog(void)
 | 
			
		||||
{
 | 
			
		||||
    /* leave some room for bound checking code */
 | 
			
		||||
    func_bound_offset = lbounds_section->data_offset;
 | 
			
		||||
    func_bound_ind = ind;
 | 
			
		||||
    func_bound_add_epilog = 0;
 | 
			
		||||
    o(0x00000013);  /* ld a0,#lbound section pointer */
 | 
			
		||||
    o(0x00000013);
 | 
			
		||||
    o(0x00000013);  /* nop -> call __bound_local_new */
 | 
			
		||||
    o(0x00000013);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void gen_bounds_epilog(void)
 | 
			
		||||
{
 | 
			
		||||
    static Sym label;
 | 
			
		||||
    addr_t saved_ind;
 | 
			
		||||
    addr_t *bounds_ptr;
 | 
			
		||||
    Sym *sym_data;
 | 
			
		||||
    int offset_modified = func_bound_offset != lbounds_section->data_offset;
 | 
			
		||||
 | 
			
		||||
    if (!offset_modified && !func_bound_add_epilog)
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
    /* add end of table info */
 | 
			
		||||
    bounds_ptr = section_ptr_add(lbounds_section, sizeof(addr_t));
 | 
			
		||||
    *bounds_ptr = 0;
 | 
			
		||||
 | 
			
		||||
    sym_data = get_sym_ref(&char_pointer_type, lbounds_section,
 | 
			
		||||
                           func_bound_offset, lbounds_section->data_offset);
 | 
			
		||||
 | 
			
		||||
    if (!label.v) {
 | 
			
		||||
        label.v = tok_alloc(".LB0 ", 4)->tok;
 | 
			
		||||
        label.type.t = VT_VOID | VT_STATIC;
 | 
			
		||||
    }
 | 
			
		||||
    /* generate bound local allocation */
 | 
			
		||||
    if (offset_modified) {
 | 
			
		||||
        saved_ind = ind;
 | 
			
		||||
        ind = func_bound_ind;
 | 
			
		||||
        label.c = 0; /* force new local ELF symbol */
 | 
			
		||||
        put_extern_sym(&label, cur_text_section, ind, 0);
 | 
			
		||||
        greloca(cur_text_section, sym_data, ind, R_RISCV_GOT_HI20, 0);
 | 
			
		||||
        o(0x17 | (10 << 7));    // auipc a0, 0 %pcrel_hi(sym)+addend
 | 
			
		||||
        greloca(cur_text_section, &label, ind, R_RISCV_PCREL_LO12_I, 0);
 | 
			
		||||
        EI(0x03, 3, 10, 10, 0); // ld a0, 0(a0)
 | 
			
		||||
        gen_bounds_call(TOK___bound_local_new);
 | 
			
		||||
        ind = saved_ind;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* generate bound check local freeing */
 | 
			
		||||
    o(0xe02a1101); /* addi sp,sp,-32  sd   a0,0(sp)   */
 | 
			
		||||
    o(0xa82ae42e); /* sd   a1,8(sp)   fsd  fa0,16(sp) */
 | 
			
		||||
    label.c = 0; /* force new local ELF symbol */
 | 
			
		||||
    put_extern_sym(&label, cur_text_section, ind, 0);
 | 
			
		||||
    greloca(cur_text_section, sym_data, ind, R_RISCV_GOT_HI20, 0);
 | 
			
		||||
    o(0x17 | (10 << 7));    // auipc a0, 0 %pcrel_hi(sym)+addend
 | 
			
		||||
    greloca(cur_text_section, &label, ind, R_RISCV_PCREL_LO12_I, 0);
 | 
			
		||||
    EI(0x03, 3, 10, 10, 0); // ld a0, 0(a0)
 | 
			
		||||
    gen_bounds_call(TOK___bound_local_delete);
 | 
			
		||||
    o(0x65a26502); /* ld   a0,0(sp)   ld   a1,8(sp)   */
 | 
			
		||||
    o(0x61052542); /* fld  fa0,16(sp) addi sp,sp,32   */
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
static void reg_pass_rec(CType *type, int *rc, int *fieldofs, int ofs)
 | 
			
		||||
{
 | 
			
		||||
    if ((type->t & VT_BTYPE) == VT_STRUCT) {
 | 
			
		||||
| 
						 | 
				
			
			@ -440,6 +580,12 @@ ST_FUNC void gfunc_call(int nb_args)
 | 
			
		|||
    int stack_adj = 0, tempspace = 0, ofs, splitofs = 0;
 | 
			
		||||
    SValue *sv;
 | 
			
		||||
    Sym *sa;
 | 
			
		||||
 | 
			
		||||
#ifdef CONFIG_TCC_BCHECK
 | 
			
		||||
    if (tcc_state->do_bounds_check)
 | 
			
		||||
        gbound_args(nb_args);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    areg[0] = 0; /* int arg regs */
 | 
			
		||||
    areg[1] = 8; /* float arg regs */
 | 
			
		||||
    sa = vtop[-nb_args].type.ref->next;
 | 
			
		||||
| 
						 | 
				
			
			@ -691,6 +837,10 @@ ST_FUNC void gfunc_prolog(Sym *func_sym)
 | 
			
		|||
            ES(0x23, 3, 8, 10 + areg[0], -8 + num_va_regs * 8); // sd aX, loc(s0)
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
#ifdef CONFIG_TCC_BCHECK
 | 
			
		||||
    if (tcc_state->do_bounds_check)
 | 
			
		||||
        gen_bounds_prolog();
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ST_FUNC int gfunc_sret(CType *vt, int variadic, CType *ret,
 | 
			
		||||
| 
						 | 
				
			
			@ -732,6 +882,11 @@ ST_FUNC void gfunc_epilog(void)
 | 
			
		|||
{
 | 
			
		||||
    int v, saved_ind, d, large_ofs_ind;
 | 
			
		||||
 | 
			
		||||
#ifdef CONFIG_TCC_BCHECK
 | 
			
		||||
    if (tcc_state->do_bounds_check)
 | 
			
		||||
        gen_bounds_epilog();
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    loc = (loc - num_va_regs * 8);
 | 
			
		||||
    d = v = (-loc + 15) & -16;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -284,11 +284,11 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr,
 | 
			
		|||
        return;
 | 
			
		||||
 | 
			
		||||
    case R_RISCV_32:
 | 
			
		||||
        write32le(ptr, val);
 | 
			
		||||
        add32le(ptr, val);
 | 
			
		||||
        return;
 | 
			
		||||
    case R_RISCV_JUMP_SLOT:
 | 
			
		||||
    case R_RISCV_64:
 | 
			
		||||
        write64le(ptr, val);
 | 
			
		||||
        add64le(ptr, val);
 | 
			
		||||
        return;
 | 
			
		||||
    case R_RISCV_ADD64:
 | 
			
		||||
        write64le(ptr, read64le(ptr) + val);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -370,7 +370,7 @@ Print statistic information at exit of program.
 | 
			
		|||
Try to continue in case of a bound checking error.
 | 
			
		||||
@end table
 | 
			
		||||
 | 
			
		||||
Note: @option{-b} is only available on i386 (linux and windows) and x86_64 (linux and windows) for the moment.
 | 
			
		||||
Note: @option{-b} is only available on i386 (linux and windows), x86_64 (linux and windows), arm, arm64 and riscv64 for the moment.
 | 
			
		||||
 | 
			
		||||
@item -bt[N]
 | 
			
		||||
Display N callers in stack traces. This is useful with @option{-g} or @option{-b}.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										6
									
								
								tcc.h
									
										
									
									
									
								
							
							
						
						
									
										6
									
								
								tcc.h
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -184,7 +184,9 @@ extern long double strtold (const char *__nptr, char **__endptr);
 | 
			
		|||
 | 
			
		||||
#if defined TCC_IS_NATIVE && !defined CONFIG_TCCBOOT
 | 
			
		||||
# define CONFIG_TCC_BACKTRACE
 | 
			
		||||
# if (defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64) \
 | 
			
		||||
# if (defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64 || \
 | 
			
		||||
      defined TCC_TARGET_ARM || defined TCC_TARGET_ARM64) || \
 | 
			
		||||
      defined TCC_TARGET_RISCV64 \
 | 
			
		||||
  && !defined TCC_UCLIBC && !defined TCC_MUSL
 | 
			
		||||
# define CONFIG_TCC_BCHECK /* enable bound checking code */
 | 
			
		||||
# endif
 | 
			
		||||
| 
						 | 
				
			
			@ -354,6 +356,7 @@ extern long double strtold (const char *__nptr, char **__endptr);
 | 
			
		|||
#elif defined TCC_TARGET_ARM64
 | 
			
		||||
# include "arm64-gen.c"
 | 
			
		||||
# include "arm64-link.c"
 | 
			
		||||
# include "arm-asm.c"
 | 
			
		||||
#elif defined TCC_TARGET_C67
 | 
			
		||||
# define TCC_TARGET_COFF
 | 
			
		||||
# include "coff.h"
 | 
			
		||||
| 
						 | 
				
			
			@ -362,6 +365,7 @@ extern long double strtold (const char *__nptr, char **__endptr);
 | 
			
		|||
#elif defined(TCC_TARGET_RISCV64)
 | 
			
		||||
# include "riscv64-gen.c"
 | 
			
		||||
# include "riscv64-link.c"
 | 
			
		||||
# include "riscv64-asm.c"
 | 
			
		||||
#else
 | 
			
		||||
#error unknown target
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										2
									
								
								tccelf.c
									
										
									
									
									
								
							
							
						
						
									
										2
									
								
								tccelf.c
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -3123,7 +3123,7 @@ ST_FUNC int tcc_load_dll(TCCState *s1, int fd, const char *filename, int level)
 | 
			
		|||
    /* test CPU specific stuff */
 | 
			
		||||
    if (ehdr.e_ident[5] != ELFDATA2LSB ||
 | 
			
		||||
        ehdr.e_machine != EM_TCC_TARGET) {
 | 
			
		||||
        tcc_error_noabort("bad architecture");
 | 
			
		||||
        tcc_error_noabort("bad architecture: %s", filename);
 | 
			
		||||
        return -1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										31
									
								
								tccgen.c
									
										
									
									
									
								
							
							
						
						
									
										31
									
								
								tccgen.c
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -886,6 +886,12 @@ ST_FUNC void put_extern_sym2(Sym *sym, int sh_num,
 | 
			
		|||
            /* XXX: avoid doing that for statics ? */
 | 
			
		||||
            /* if bound checking is activated, we change some function
 | 
			
		||||
               names by adding the "__bound" prefix */
 | 
			
		||||
#if defined(TCC_TARGET_ARM) && defined(TCC_ARM_EABI)
 | 
			
		||||
            if (strcmp (name, "memcpy") == 0 ||
 | 
			
		||||
                strcmp (name, "memmove") == 0 ||
 | 
			
		||||
                strcmp (name, "memset") == 0)
 | 
			
		||||
                goto add_bound;
 | 
			
		||||
#endif
 | 
			
		||||
            switch(sym->v) {
 | 
			
		||||
#ifdef TCC_TARGET_PE
 | 
			
		||||
            /* XXX: we rely only on malloc hooks */
 | 
			
		||||
| 
						 | 
				
			
			@ -897,6 +903,10 @@ ST_FUNC void put_extern_sym2(Sym *sym, int sh_num,
 | 
			
		|||
#endif
 | 
			
		||||
            case TOK_memcpy:
 | 
			
		||||
            case TOK_memmove:
 | 
			
		||||
#if defined(TCC_TARGET_ARM) && defined(TCC_ARM_EABI)
 | 
			
		||||
            case TOK_memmove4:
 | 
			
		||||
            case TOK_memmove8:
 | 
			
		||||
#endif
 | 
			
		||||
            case TOK_memset:
 | 
			
		||||
            case TOK_memcmp:
 | 
			
		||||
            case TOK_strlen:
 | 
			
		||||
| 
						 | 
				
			
			@ -907,12 +917,17 @@ ST_FUNC void put_extern_sym2(Sym *sym, int sh_num,
 | 
			
		|||
            case TOK_strcat:
 | 
			
		||||
            case TOK_strchr:
 | 
			
		||||
            case TOK_strdup:
 | 
			
		||||
#if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64
 | 
			
		||||
            case TOK_alloca:
 | 
			
		||||
#endif
 | 
			
		||||
            case TOK_mmap:
 | 
			
		||||
            case TOK_munmap:
 | 
			
		||||
            case TOK_longjmp:
 | 
			
		||||
#ifndef TCC_TARGET_PE
 | 
			
		||||
            case TOK_siglongjmp:
 | 
			
		||||
#endif
 | 
			
		||||
#if defined(TCC_TARGET_ARM) && defined(TCC_ARM_EABI)
 | 
			
		||||
add_bound:
 | 
			
		||||
#endif
 | 
			
		||||
                strcpy(buf, "__bound_");
 | 
			
		||||
                strcat(buf, name);
 | 
			
		||||
| 
						 | 
				
			
			@ -3820,9 +3835,9 @@ ST_FUNC void vstore(void)
 | 
			
		|||
            /* address of memcpy() */
 | 
			
		||||
#ifdef TCC_ARM_EABI
 | 
			
		||||
            if(!(align & 7))
 | 
			
		||||
                vpush_global_sym(&func_old_type, TOK_memcpy8);
 | 
			
		||||
                vpush_global_sym(&func_old_type, TOK_memmove8);
 | 
			
		||||
            else if(!(align & 3))
 | 
			
		||||
                vpush_global_sym(&func_old_type, TOK_memcpy4);
 | 
			
		||||
                vpush_global_sym(&func_old_type, TOK_memmove4);
 | 
			
		||||
            else
 | 
			
		||||
#endif
 | 
			
		||||
            /* Use memmove, rather than memcpy, as dest and src may be same: */
 | 
			
		||||
| 
						 | 
				
			
			@ -5636,13 +5651,25 @@ ST_FUNC void unary(void)
 | 
			
		|||
            mk_pointer(&type);
 | 
			
		||||
            vset(&type, VT_LOCAL, 0);       /* local frame */
 | 
			
		||||
            while (level--) {
 | 
			
		||||
#ifdef TCC_TARGET_RISCV64
 | 
			
		||||
                vpushi(2*PTR_SIZE);
 | 
			
		||||
                gen_op('-');
 | 
			
		||||
#endif
 | 
			
		||||
                mk_pointer(&vtop->type);
 | 
			
		||||
                indir();                    /* -> parent frame */
 | 
			
		||||
            }
 | 
			
		||||
            if (tok1 == TOK_builtin_return_address) {
 | 
			
		||||
                // assume return address is just above frame pointer on stack
 | 
			
		||||
#ifdef TCC_TARGET_ARM
 | 
			
		||||
                vpushi(2*PTR_SIZE);
 | 
			
		||||
                gen_op('+');
 | 
			
		||||
#elif defined TCC_TARGET_RISCV64
 | 
			
		||||
                vpushi(PTR_SIZE);
 | 
			
		||||
                gen_op('-');
 | 
			
		||||
#else
 | 
			
		||||
                vpushi(PTR_SIZE);
 | 
			
		||||
                gen_op('+');
 | 
			
		||||
#endif
 | 
			
		||||
                mk_pointer(&vtop->type);
 | 
			
		||||
                indir();
 | 
			
		||||
            }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										37
									
								
								tccrun.c
									
										
									
									
									
								
							
							
						
						
									
										37
									
								
								tccrun.c
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -648,10 +648,12 @@ static void rt_getcontext(ucontext_t *uc, rt_context *rc)
 | 
			
		|||
#elif defined(__arm__)
 | 
			
		||||
    rc->ip = uc->uc_mcontext.arm_pc;
 | 
			
		||||
    rc->fp = uc->uc_mcontext.arm_fp;
 | 
			
		||||
    rc->sp = uc->uc_mcontext.arm_sp;
 | 
			
		||||
#elif defined(__aarch64__)
 | 
			
		||||
    rc->ip = uc->uc_mcontext.pc;
 | 
			
		||||
    rc->fp = uc->uc_mcontext.regs[29];
 | 
			
		||||
#elif defined(__riscv)
 | 
			
		||||
    rc->ip = uc->uc_mcontext.__gregs[REG_PC];
 | 
			
		||||
    rc->fp = uc->uc_mcontext.__gregs[REG_S0];
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -805,22 +807,9 @@ static int rt_get_caller_pc(addr_t *paddr, rt_context *rc, int level)
 | 
			
		|||
        *paddr = rc->ip;
 | 
			
		||||
    } else {
 | 
			
		||||
        addr_t fp = rc->fp;
 | 
			
		||||
        addr_t sp = rc->sp;
 | 
			
		||||
        if (sp < 0x1000)
 | 
			
		||||
            sp = 0x1000;
 | 
			
		||||
        /* XXX: specific to tinycc stack frames */
 | 
			
		||||
        if (fp < sp + 12 || fp & 3)
 | 
			
		||||
            return -1;
 | 
			
		||||
        while (--level) {
 | 
			
		||||
            sp = ((addr_t *)fp)[-2];
 | 
			
		||||
            if (sp < fp || sp - fp > 16 || sp & 3)
 | 
			
		||||
                return -1;
 | 
			
		||||
            fp = ((addr_t *)fp)[-3];
 | 
			
		||||
            if (fp <= sp || fp - sp < 12 || fp & 3)
 | 
			
		||||
                return -1;
 | 
			
		||||
        }
 | 
			
		||||
        /* XXX: check address validity with program info */
 | 
			
		||||
        *paddr = ((addr_t *)fp)[-1];
 | 
			
		||||
        while (--level)
 | 
			
		||||
            fp = ((addr_t *)fp)[0];
 | 
			
		||||
        *paddr = ((addr_t *)fp)[2];
 | 
			
		||||
    }
 | 
			
		||||
    return 0;
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			@ -840,6 +829,20 @@ static int rt_get_caller_pc(addr_t *paddr, rt_context *rc, int level)
 | 
			
		|||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#elif defined(__riscv)
 | 
			
		||||
static int rt_get_caller_pc(addr_t *paddr, rt_context *rc, int level)
 | 
			
		||||
{
 | 
			
		||||
    if (level == 0) {
 | 
			
		||||
        *paddr = rc->ip;
 | 
			
		||||
    } else {
 | 
			
		||||
        addr_t *fp = (addr_t*)rc->fp;
 | 
			
		||||
        while (--level)
 | 
			
		||||
            fp = (addr_t *)fp[-2];
 | 
			
		||||
        *paddr = fp[-1];
 | 
			
		||||
    }
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#else
 | 
			
		||||
#warning add arch specific rt_get_caller_pc()
 | 
			
		||||
static int rt_get_caller_pc(addr_t *paddr, rt_context *rc, int level)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										4
									
								
								tcctok.h
									
										
									
									
									
								
							
							
						
						
									
										4
									
								
								tcctok.h
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -205,9 +205,9 @@
 | 
			
		|||
#if defined TCC_TARGET_ARM
 | 
			
		||||
# ifdef TCC_ARM_EABI
 | 
			
		||||
     DEF(TOK_memcpy, "__aeabi_memcpy")
 | 
			
		||||
     DEF(TOK_memcpy4, "__aeabi_memcpy4")
 | 
			
		||||
     DEF(TOK_memcpy8, "__aeabi_memcpy8")
 | 
			
		||||
     DEF(TOK_memmove, "__aeabi_memmove")
 | 
			
		||||
     DEF(TOK_memmove4, "__aeabi_memmove4")
 | 
			
		||||
     DEF(TOK_memmove8, "__aeabi_memmove8")
 | 
			
		||||
     DEF(TOK_memset, "__aeabi_memset")
 | 
			
		||||
     DEF(TOK___aeabi_ldivmod, "__aeabi_ldivmod")
 | 
			
		||||
     DEF(TOK___aeabi_uldivmod, "__aeabi_uldivmod")
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -35,6 +35,15 @@ endif
 | 
			
		|||
ifeq ($(ARCH),x86_64)
 | 
			
		||||
 TESTS += $(BTESTS)
 | 
			
		||||
endif
 | 
			
		||||
ifeq ($(ARCH),arm)
 | 
			
		||||
 TESTS += $(BTESTS)
 | 
			
		||||
endif
 | 
			
		||||
ifeq ($(ARCH),arm64)
 | 
			
		||||
 TESTS += $(BTESTS)
 | 
			
		||||
endif
 | 
			
		||||
ifeq ($(ARCH),riscv64)
 | 
			
		||||
 TESTS += $(BTESTS)
 | 
			
		||||
endif
 | 
			
		||||
endif
 | 
			
		||||
ifdef CONFIG_OSX # -run only
 | 
			
		||||
 TESTS := hello-run libtest tests2-dir pp-dir
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -169,21 +169,34 @@ int test13(void)
 | 
			
		|||
    return strlen(tab);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if defined __i386__ || defined __x86_64__
 | 
			
		||||
#define allocf(x)
 | 
			
		||||
#else
 | 
			
		||||
#define alloca(x) malloc(x)
 | 
			
		||||
#define allocf(x) free(x)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
int test14(void)
 | 
			
		||||
{
 | 
			
		||||
    char *p = alloca(TAB_SIZE);
 | 
			
		||||
    size_t ret;
 | 
			
		||||
    memset(p, 'a', TAB_SIZE);
 | 
			
		||||
    p[TAB_SIZE-1] = 0;
 | 
			
		||||
    return strlen(p);
 | 
			
		||||
    ret = strlen(p);
 | 
			
		||||
    allocf(p);
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* error */
 | 
			
		||||
int test15(void)
 | 
			
		||||
{
 | 
			
		||||
    char *p = alloca(TAB_SIZE-1);
 | 
			
		||||
    size_t ret;
 | 
			
		||||
    memset(p, 'a', TAB_SIZE);
 | 
			
		||||
    p[TAB_SIZE-1] = 0;
 | 
			
		||||
    return strlen(p);
 | 
			
		||||
    ret = strlen(p);
 | 
			
		||||
    allocf(p);
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* ok */
 | 
			
		||||
| 
						 | 
				
			
			@ -194,6 +207,7 @@ int test16()
 | 
			
		|||
 | 
			
		||||
    p = alloca(16);
 | 
			
		||||
    strcpy(p,"12345678901234");
 | 
			
		||||
    allocf(p);
 | 
			
		||||
 | 
			
		||||
    /* Test alloca embedded in a larger expression */
 | 
			
		||||
    printf("alloca : %s : %s\n", p, strcpy(alloca(strlen(demo)+1),demo) );
 | 
			
		||||
| 
						 | 
				
			
			@ -209,6 +223,7 @@ int test17()
 | 
			
		|||
 | 
			
		||||
    p = alloca(16);
 | 
			
		||||
    strcpy(p,"12345678901234");
 | 
			
		||||
    allocf(p);
 | 
			
		||||
 | 
			
		||||
    /* Test alloca embedded in a larger expression */
 | 
			
		||||
    printf("alloca : %s : %s\n", p, strcpy(alloca(strlen(demo)),demo) );
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -23,8 +23,11 @@ ifeq (,$(filter i386,$(ARCH)))
 | 
			
		|||
 SKIP += 98_al_ax_extend.test 99_fastcall.test
 | 
			
		||||
endif
 | 
			
		||||
ifeq (,$(filter i386 x86_64,$(ARCH)))
 | 
			
		||||
 SKIP += 85_asm-outside-function.test
 | 
			
		||||
 SKIP += 112_backtrace.test 113_btdll.test
 | 
			
		||||
 SKIP += 85_asm-outside-function.test # x86 asm
 | 
			
		||||
 SKIP += 113_btdll.test # dll support needed
 | 
			
		||||
endif
 | 
			
		||||
ifeq (,$(filter i386 x86_64 arm arm64 riscv64,$(ARCH)))
 | 
			
		||||
 SKIP += 112_backtrace.test
 | 
			
		||||
 SKIP += 114_bound_signal.test
 | 
			
		||||
 SKIP += 115_bound_setjmp.test
 | 
			
		||||
 SKIP += 116_bound_setjmp2.test
 | 
			
		||||
| 
						 | 
				
			
			@ -82,7 +85,7 @@ GEN-ALWAYS =
 | 
			
		|||
 | 
			
		||||
112_backtrace.test: FLAGS += -dt -b
 | 
			
		||||
112_backtrace.test 113_btdll.test: FILTER += \
 | 
			
		||||
    -e 's;[0-9A-Fa-fx]\{8,\};........;g' \
 | 
			
		||||
    -e 's;[0-9A-Fa-fx]\{5,\};........;g' \
 | 
			
		||||
    -e 's;0x[0-9A-Fa-f]\+;0x?;g'
 | 
			
		||||
 | 
			
		||||
# this test creates two DLLs and an EXE
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -744,8 +744,9 @@ static void gen_bounds_epilog(void)
 | 
			
		|||
    addr_t saved_ind;
 | 
			
		||||
    addr_t *bounds_ptr;
 | 
			
		||||
    Sym *sym_data;
 | 
			
		||||
    int offset_modified = func_bound_offset != lbounds_section->data_offset;
 | 
			
		||||
 | 
			
		||||
    if (func_bound_offset == lbounds_section->data_offset && !func_bound_add_epilog)
 | 
			
		||||
    if (!offset_modified && !func_bound_add_epilog)
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
    /* add end of table info */
 | 
			
		||||
| 
						 | 
				
			
			@ -756,7 +757,7 @@ static void gen_bounds_epilog(void)
 | 
			
		|||
                           func_bound_offset, lbounds_section->data_offset);
 | 
			
		||||
 | 
			
		||||
    /* generate bound local allocation */
 | 
			
		||||
    if (func_bound_offset != lbounds_section->data_offset) {
 | 
			
		||||
    if (offset_modified) {
 | 
			
		||||
        saved_ind = ind;
 | 
			
		||||
        ind = func_bound_ind;
 | 
			
		||||
        greloca(cur_text_section, sym_data, ind + 2, R_X86_64_64, 0);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		
		Reference in a new issue