boot2

Playing with the boostrap
git clone https://git.ryansepassi.com/git/boot2.git
Log | Files | Refs | README

132-tentative-bss-sizing.c (2502B)


      1 /* C 6.9.2 — tentative defs reserve sizeof(T) bytes of zero-init
      2  * storage. Companion to 124-tentative-static.c, which only exercised
      3  * `int`. tcc-boot2 needs the wide-pointer / array cases too:
      4  * mes/globals.c declares `char **environ;`, `int errno;`, etc.
      5  * cc.scm has been emitting too few or too many bytes for these
      6  * (see :environ → 1 byte, :errno → 16 bytes in libc.P1pp).
      7  *
      8  * Each global is sized differently and probed via address-of so the
      9  * compiler can't fold the read. Wrong sizing manifests as either:
     10  *   - reads past the slot return 0xff... or stale data → mismatch
     11  *   - 8-byte stores to a 1-byte slot scribble adjacent globals
     12  *     (so writing g_pp = X then reading g_int near it shows X
     13  *     bleeding through). */
     14 
     15 char       g_char;            /* 1 byte */
     16 short      g_short;           /* 2 bytes */
     17 int        g_int;             /* 4 bytes */
     18 long       g_long;            /* one target word */
     19 char      *g_p;               /* one target word */
     20 char     **g_pp;              /* one target word — the environ shape */
     21 int        g_arr[4];          /* 16 bytes */
     22 char      *g_parr[3];         /* three target words */
     23 
     24 int
     25 main (void)
     26 {
     27   /* Tentative defs must zero-init. */
     28   if (g_char  != 0) return 1;
     29   if (g_short != 0) return 2;
     30   if (g_int   != 0) return 3;
     31   if (g_long  != 0) return 4;
     32   if (g_p     != 0) return 5;
     33   if (g_pp    != 0) return 6;
     34   if (g_arr[0] || g_arr[1] || g_arr[2] || g_arr[3])
     35     return 7;
     36   if (g_parr[0] || g_parr[1] || g_parr[2])
     37     return 8;
     38 
     39   /* Each slot must be addressable for its full sizeof(T).
     40    * Write a sentinel through the address, read it back. If the
     41    * slot is undersized, the high bytes spill into the next global
     42    * and the read returns a truncated value. */
     43   long *pl = &g_long;
     44   long long_sentinel = (long)0x1122334455667788L;
     45   *pl = long_sentinel;
     46   if (g_long != long_sentinel)
     47     return 9;
     48 
     49   long ptr_sentinel = (long)0xdeadbeef00112233L;
     50   g_pp = (char **) ptr_sentinel;
     51   if ((long) g_pp != ptr_sentinel)
     52     return 10;
     53 
     54   /* Array element: write the last slot — only valid if the full
     55    * array allocation actually exists. */
     56   g_arr[3] = 42;
     57   if (g_arr[3] != 42) return 11;
     58   g_parr[2] = (char *) 0x99;
     59   if ((long) g_parr[2] != 0x99) return 12;
     60 
     61   /* And no spill: writing g_pp must NOT change g_int next door.
     62    * (Slot order in memory follows declaration order in the TU.) */
     63   g_int = 0;
     64   g_pp  = (char **) 0xfffffffffffffffeL;
     65   if (g_int != 0) return 13;
     66 
     67   return 0;
     68 }