boot2

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

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


      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;            /* 8 bytes */
     19 char      *g_p;               /* 8 bytes */
     20 char     **g_pp;              /* 8 bytes — the environ shape */
     21 int        g_arr[4];          /* 16 bytes */
     22 char      *g_parr[3];         /* 24 bytes */
     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   *pl = 0x1122334455667788L;
     45   if (g_long != 0x1122334455667788L)
     46     return 9;
     47 
     48   g_pp = (char **) 0xdeadbeef00112233L;
     49   if ((long) g_pp != (long) 0xdeadbeef00112233L)
     50     return 10;
     51 
     52   /* Array element: write the last slot — only valid if the full
     53    * 16-byte / 24-byte allocation actually exists. */
     54   g_arr[3] = 42;
     55   if (g_arr[3] != 42) return 11;
     56   g_parr[2] = (char *) 0x99;
     57   if ((long) g_parr[2] != 0x99) return 12;
     58 
     59   /* And no spill: writing g_pp must NOT change g_int next door.
     60    * (Slot order in memory follows declaration order in the TU.) */
     61   g_int = 0;
     62   g_pp  = (char **) 0xfffffffffffffffeL;
     63   if (g_int != 0) return 13;
     64 
     65   return 0;
     66 }