struct-ret-check.c
来自「用于进行gcc测试」· C语言 代码 · 共 127 行
C
127 行
/* Copyright (C) 2006 Free Software Foundation, Inc. *//* Contributed by Carlos O'Donell on 2006-03-14 *//* Test that GCC follows the SPARC 32-bit psABI with regards to structure return checking in a callee. When -mstd-struct-return is specificed then gcc will emit code to skip the unimp insn. */ /* Origin: Carlos O'Donell <carlos@codesourcery.com> *//* { dg-do run { target sparc*-*-solaris* sparc*-*-linux* sparc*-*-*bsd* } } *//* { dg-options "-mstd-struct-return" } *//* { dg-require-effective-target ilp32 } */#include <stdio.h>#include <stdlib.h>#include <signal.h>/* Local declaration of div_t structure */struct mydiv_t { int rem; int quot;};/* Global check variable used by signal handler */int check = 1;struct mydiv_t dcheck;struct mydiv_t foo (void){ struct mydiv_t bar; bar.rem = 3; bar.quot = 4; return bar;}void handle_sigill (int signum){ if (signum == SIGILL && check == 2) { /* We expected a SIGILL due to a mismatch in unimp size and struct mydiv_t size */ exit (0); } else abort ();}/* Implement 3 checks to validate SPARC 32-bit psABI callee returns struct Test1: Save area is valid. unimp size is valid. Success: Save area modified correctly. Failure: Save area unmodified. Test2: Save area is valid. unimp size is invalid (invalid insn). Success: Save area unmodified. check == 2. Failure: Save area modified or check == 1. Test3: Save area is invalid. unimp size is invalid (invalid size). Success: Will raise a SIGILL. Failure: SIGSEGV caused by write to invalid save area. */int main (void){ dcheck.rem = 1; dcheck.quot = 2; /*** Test1 ***/ /* Insert a call, insert unimp by hand */ __asm__ ("st %1, [ %%sp + 0x40 ]\n\t" "call foo\n\t" " nop\n\t" "unimp %2\n\t" : "=m" (dcheck) : "r" (&dcheck), "i" (sizeof(struct mydiv_t)) : "memory"); /* If the caller doesn't adjust the return, then it crashes. Check the result too. */ if ((dcheck.rem != 3) || (dcheck.quot !=4)) abort (); /*** Test 2 ***/ dcheck.rem = 1; dcheck.quot = 2; /* Ignore the return of the function */ __asm__ ("st %3, [ %%sp + 0x40 ]\n\t" "call foo\n\t" " nop\n\t" "mov %2, %0\n\t" : "+r" (check), "=m" (dcheck) : "i" (0x2), "r" (&dcheck) : "memory"); /* If the caller does an unconditional adjustment it will skip the mov, and then we can fail the test based on check's value We pass a valid pointer to a save area in order to check if caller incorrectly wrote to the save area aswell. There may be a case where the unimp check and skip is correct, but the write to the save area still occurs. */ if (check != 2) abort (); if ((dcheck.rem != 1) || (dcheck.quot != 2)) abort (); /*** Test 3 ***/ /* Prepare a test that must SIGILL. According to the spec if the sizes of the save area and return don't match then the copy is ignored and we return to the unimp. */ signal (SIGILL, handle_sigill); __asm__ ("st %%g0, [ %%sp + 0x40 ]\n\t" "call foo\n\t" " nop\n\t" "unimp %0\n\t" : /* No outputs */ : "i" (sizeof(struct mydiv_t)-1) : "memory"); /* NEVER REACHED */ exit (0);}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?