Ben Gamari pushed to branch wip/T25989 at Glasgow Haskell Compiler / GHC

Commits:

8 changed files:

Changes:

  • rts/Linker.c
    ... ... @@ -1194,7 +1194,7 @@ void freeObjectCode (ObjectCode *oc)
    1194 1194
             stgFree(oc->sections);
    
    1195 1195
         }
    
    1196 1196
     
    
    1197
    -    freeProddableBlocks(oc);
    
    1197
    +    freeProddableBlocks(&oc->proddables);
    
    1198 1198
         freeSegments(oc);
    
    1199 1199
     
    
    1200 1200
         /* Free symbol_extras.  On x86_64 Windows, symbol_extras are allocated
    
    ... ... @@ -1279,7 +1279,7 @@ mkOc( ObjectType type, pathchar *path, char *image, int imageSize,
    1279 1279
        oc->sections          = NULL;
    
    1280 1280
        oc->n_segments        = 0;
    
    1281 1281
        oc->segments          = NULL;
    
    1282
    -   oc->proddables        = NULL;
    
    1282
    +   initProddableBlockSet(&oc->proddables);
    
    1283 1283
        oc->foreign_exports   = NULL;
    
    1284 1284
     #if defined(NEED_SYMBOL_EXTRAS)
    
    1285 1285
        oc->symbol_extras     = NULL;
    
    ... ... @@ -1834,50 +1834,6 @@ OStatus getObjectLoadStatus (pathchar *path)
    1834 1834
         return r;
    
    1835 1835
     }
    
    1836 1836
     
    
    1837
    -/* -----------------------------------------------------------------------------
    
    1838
    - * Sanity checking.  For each ObjectCode, maintain a list of address ranges
    
    1839
    - * which may be prodded during relocation, and abort if we try and write
    
    1840
    - * outside any of these.
    
    1841
    - */
    
    1842
    -void
    
    1843
    -addProddableBlock ( ObjectCode* oc, void* start, int size )
    
    1844
    -{
    
    1845
    -   ProddableBlock* pb
    
    1846
    -      = stgMallocBytes(sizeof(ProddableBlock), "addProddableBlock");
    
    1847
    -
    
    1848
    -   IF_DEBUG(linker, debugBelch("addProddableBlock: %p %p %d\n", oc, start, size));
    
    1849
    -   ASSERT(size > 0);
    
    1850
    -   pb->start      = start;
    
    1851
    -   pb->size       = size;
    
    1852
    -   pb->next       = oc->proddables;
    
    1853
    -   oc->proddables = pb;
    
    1854
    -}
    
    1855
    -
    
    1856
    -void
    
    1857
    -checkProddableBlock (ObjectCode *oc, void *addr, size_t size )
    
    1858
    -{
    
    1859
    -   ProddableBlock* pb;
    
    1860
    -
    
    1861
    -   for (pb = oc->proddables; pb != NULL; pb = pb->next) {
    
    1862
    -      char* s = (char*)(pb->start);
    
    1863
    -      char* e = s + pb->size;
    
    1864
    -      char* a = (char*)addr;
    
    1865
    -      if (a >= s && (a+size) <= e) return;
    
    1866
    -   }
    
    1867
    -   barf("checkProddableBlock: invalid fixup in runtime linker: %p", addr);
    
    1868
    -}
    
    1869
    -
    
    1870
    -void freeProddableBlocks (ObjectCode *oc)
    
    1871
    -{
    
    1872
    -    ProddableBlock *pb, *next;
    
    1873
    -
    
    1874
    -    for (pb = oc->proddables; pb != NULL; pb = next) {
    
    1875
    -        next = pb->next;
    
    1876
    -        stgFree(pb);
    
    1877
    -    }
    
    1878
    -    oc->proddables = NULL;
    
    1879
    -}
    
    1880
    -
    
    1881 1837
     /* -----------------------------------------------------------------------------
    
    1882 1838
      * Section management.
    
    1883 1839
      */
    

  • rts/LinkerInternals.h
    ... ... @@ -12,6 +12,7 @@
    12 12
     #include "RtsSymbols.h"
    
    13 13
     #include "Hash.h"
    
    14 14
     #include "linker/M32Alloc.h"
    
    15
    +#include "linker/ProddableBlocks.h"
    
    15 16
     
    
    16 17
     #if RTS_LINKER_USE_MMAP
    
    17 18
     #include <sys/mman.h>
    
    ... ... @@ -175,14 +176,6 @@ struct _Section {
    175 176
       struct SectionFormatInfo* info;
    
    176 177
     };
    
    177 178
     
    
    178
    -typedef
    
    179
    -   struct _ProddableBlock {
    
    180
    -      void* start;
    
    181
    -      int   size;
    
    182
    -      struct _ProddableBlock* next;
    
    183
    -   }
    
    184
    -   ProddableBlock;
    
    185
    -
    
    186 179
     typedef struct _Segment {
    
    187 180
         void *start;                /* page aligned start address of a segment */
    
    188 181
         size_t size;                /* page rounded size of a segment */
    
    ... ... @@ -328,7 +321,7 @@ struct _ObjectCode {
    328 321
         /* SANITY CHECK ONLY: a list of the only memory regions which may
    
    329 322
            safely be prodded during relocation.  Any attempt to prod
    
    330 323
            outside one of these is an error in the linker. */
    
    331
    -    ProddableBlock* proddables;
    
    324
    +    ProddableBlockSet proddables;
    
    332 325
     
    
    333 326
     #if defined(NEED_SYMBOL_EXTRAS)
    
    334 327
         SymbolExtra    *symbol_extras;
    
    ... ... @@ -434,10 +427,6 @@ void exitLinker( void );
    434 427
     void freeObjectCode (ObjectCode *oc);
    
    435 428
     SymbolAddr* loadSymbol(SymbolName *lbl, RtsSymbolInfo *pinfo);
    
    436 429
     
    
    437
    -void addProddableBlock ( ObjectCode* oc, void* start, int size );
    
    438
    -void checkProddableBlock (ObjectCode *oc, void *addr, size_t size );
    
    439
    -void freeProddableBlocks (ObjectCode *oc);
    
    440
    -
    
    441 430
     void addSection (Section *s, SectionKind kind, SectionAlloc alloc,
    
    442 431
                      void* start, StgWord size, StgWord mapped_offset,
    
    443 432
                      void* mapped_start, StgWord mapped_size);
    

  • rts/linker/Elf.c
    ... ... @@ -924,7 +924,7 @@ ocGetNames_ELF ( ObjectCode* oc )
    924 924
               oc->sections[i].info->stubs = NULL;
    
    925 925
     #endif
    
    926 926
     
    
    927
    -          addProddableBlock(oc, start, size);
    
    927
    +          addProddableBlock(&oc->proddables, start, size);
    
    928 928
           } else {
    
    929 929
               addSection(&oc->sections[i], kind, alloc, oc->image+offset, size,
    
    930 930
                          0, 0, 0);
    
    ... ... @@ -1272,7 +1272,7 @@ do_Elf_Rel_relocations ( ObjectCode* oc, char* ehdrC,
    1272 1272
                     debugBelch("Reloc: P = %p   S = %p   A = %p   type=%d\n",
    
    1273 1273
                                (void*)P, (void*)S, (void*)A, reloc_type ));
    
    1274 1274
     #if defined(DEBUG)
    
    1275
    -       checkProddableBlock ( oc, pP, sizeof(Elf_Word) );
    
    1275
    +       checkProddableBlock ( &oc->proddables, pP, sizeof(Elf_Word) );
    
    1276 1276
     #else
    
    1277 1277
            (void) pP; /* suppress unused varialbe warning in non-debug build */
    
    1278 1278
     #endif
    
    ... ... @@ -1684,7 +1684,7 @@ do_Elf_Rela_relocations ( ObjectCode* oc, char* ehdrC,
    1684 1684
     #if defined(DEBUG)
    
    1685 1685
           IF_DEBUG(linker_verbose,debugBelch("Reloc: P = %p   S = %p   A = %p\n",
    
    1686 1686
                                              (void*)P, (void*)S, (void*)A ));
    
    1687
    -      checkProddableBlock(oc, (void*)P, sizeof(Elf_Word));
    
    1687
    +      checkProddableBlock(&oc->proddables, (void*)P, sizeof(Elf_Word));
    
    1688 1688
     #endif
    
    1689 1689
     
    
    1690 1690
     #if defined(powerpc_HOST_ARCH) || defined(x86_64_HOST_ARCH)
    

  • rts/linker/MachO.c
    ... ... @@ -253,7 +253,7 @@ resolveImports(
    253 253
                 return 0;
    
    254 254
             }
    
    255 255
     
    
    256
    -        checkProddableBlock(oc,
    
    256
    +        checkProddableBlock(&oc->proddables,
    
    257 257
                                 ((void**)(oc->image + sect->offset)) + i,
    
    258 258
                                 sizeof(void *));
    
    259 259
             ((void**)(oc->image + sect->offset))[i] = addr;
    
    ... ... @@ -287,7 +287,7 @@ decodeAddend(ObjectCode * oc, Section * section, MachORelocationInfo * ri) {
    287 287
         /* the instruction. It is 32bit wide */
    
    288 288
         uint32_t * p = (uint32_t*)((uint8_t*)section->start + ri->r_address);
    
    289 289
     
    
    290
    -    checkProddableBlock(oc, (void*)p, 1 << ri->r_length);
    
    290
    +    checkProddableBlock(&oc->proddables, (void*)p, 1 << ri->r_length);
    
    291 291
     
    
    292 292
         switch(ri->r_type) {
    
    293 293
             case ARM64_RELOC_UNSIGNED: {
    
    ... ... @@ -364,7 +364,7 @@ encodeAddend(ObjectCode * oc, Section * section,
    364 364
                  MachORelocationInfo * ri, int64_t addend) {
    
    365 365
         uint32_t * p = (uint32_t*)((uint8_t*)section->start + ri->r_address);
    
    366 366
     
    
    367
    -    checkProddableBlock(oc, (void*)p, 1 << ri->r_length);
    
    367
    +    checkProddableBlock(&oc->proddables, (void*)p, 1 << ri->r_length);
    
    368 368
     
    
    369 369
         switch (ri->r_type) {
    
    370 370
             case ARM64_RELOC_UNSIGNED: {
    
    ... ... @@ -788,7 +788,7 @@ relocateSection(ObjectCode* oc, int curSection)
    788 788
                 default:
    
    789 789
                     barf("Unknown size.");
    
    790 790
             }
    
    791
    -        checkProddableBlock(oc,thingPtr,relocLenBytes);
    
    791
    +        checkProddableBlock(&oc->proddables,thingPtr,relocLenBytes);
    
    792 792
     
    
    793 793
             /*
    
    794 794
              * With SIGNED_N the relocation is not at the end of the
    
    ... ... @@ -1034,9 +1034,9 @@ relocateSection(ObjectCode* oc, int curSection)
    1034 1034
              */
    
    1035 1035
             if (0 == reloc->r_extern) {
    
    1036 1036
                 if (reloc->r_pcrel) {
    
    1037
    -                checkProddableBlock(oc, (void *)((char *)thing + baseValue), 1);
    
    1037
    +                checkProddableBlock(&oc->proddables, (void *)((char *)thing + baseValue), 1);
    
    1038 1038
                 } else {
    
    1039
    -                checkProddableBlock(oc, (void *)thing, 1);
    
    1039
    +                checkProddableBlock(&oc->proddables, (void *)thing, 1);
    
    1040 1040
                 }
    
    1041 1041
             }
    
    1042 1042
     
    
    ... ... @@ -1343,7 +1343,7 @@ ocGetNames_MachO(ObjectCode* oc)
    1343 1343
                     secArray[sec_idx].info->stub_size = 0;
    
    1344 1344
                     secArray[sec_idx].info->stubs = NULL;
    
    1345 1345
     #endif
    
    1346
    -                addProddableBlock(oc, start, section->size);
    
    1346
    +                addProddableBlock(&oc->proddables, start, section->size);
    
    1347 1347
                 }
    
    1348 1348
     
    
    1349 1349
                 curMem = (char*) secMem + section->size;
    

  • rts/linker/PEi386.c
    ... ... @@ -1658,7 +1658,7 @@ ocGetNames_PEi386 ( ObjectCode* oc )
    1658 1658
           }
    
    1659 1659
     
    
    1660 1660
           addSection(section, kind, SECTION_NOMEM, start, sz, 0, 0, 0);
    
    1661
    -      addProddableBlock(oc, oc->sections[i].start, sz);
    
    1661
    +      addProddableBlock(&oc->proddables, oc->sections[i].start, sz);
    
    1662 1662
        }
    
    1663 1663
     
    
    1664 1664
        /* Copy exported symbols into the ObjectCode. */
    
    ... ... @@ -1690,7 +1690,7 @@ ocGetNames_PEi386 ( ObjectCode* oc )
    1690 1690
                       SECTIONKIND_RWDATA, SECTION_MALLOC,
    
    1691 1691
                       bss, globalBssSize, 0, 0, 0);
    
    1692 1692
            IF_DEBUG(linker_verbose, debugBelch("bss @ %p %" FMT_Word "\n", bss, globalBssSize));
    
    1693
    -       addProddableBlock(oc, bss, globalBssSize);
    
    1693
    +       addProddableBlock(&oc->proddables, bss, globalBssSize);
    
    1694 1694
        } else {
    
    1695 1695
            addSection(&oc->sections[oc->n_sections-1],
    
    1696 1696
                       SECTIONKIND_OTHER, SECTION_NOMEM, NULL, 0, 0, 0, 0);
    
    ... ... @@ -2067,13 +2067,13 @@ ocResolve_PEi386 ( ObjectCode* oc )
    2067 2067
              IF_DEBUG(linker_verbose, debugBelch("S=%zx\n", S));
    
    2068 2068
     
    
    2069 2069
              /* All supported relocations write at least 4 bytes */
    
    2070
    -         checkProddableBlock(oc, pP, 4);
    
    2070
    +         checkProddableBlock(&oc->proddables, pP, 4);
    
    2071 2071
              switch (reloc->Type) {
    
    2072 2072
     #if defined(x86_64_HOST_ARCH)
    
    2073 2073
                 case 1: /* R_X86_64_64 (ELF constant 1) - IMAGE_REL_AMD64_ADDR64 (PE constant 1) */
    
    2074 2074
                    {
    
    2075 2075
                        uint64_t A;
    
    2076
    -                   checkProddableBlock(oc, pP, 8);
    
    2076
    +                   checkProddableBlock(&oc->proddables, pP, 8);
    
    2077 2077
                        A = *(uint64_t*)pP;
    
    2078 2078
                        *(uint64_t *)pP = S + A;
    
    2079 2079
                        break;
    
    ... ... @@ -2114,7 +2114,7 @@ ocResolve_PEi386 ( ObjectCode* oc )
    2114 2114
                    {
    
    2115 2115
                        /* mingw will emit this for a pc-rel 64 relocation */
    
    2116 2116
                        uint64_t A;
    
    2117
    -                   checkProddableBlock(oc, pP, 8);
    
    2117
    +                   checkProddableBlock(&oc->proddables, pP, 8);
    
    2118 2118
                        A = *(uint64_t*)pP;
    
    2119 2119
                        *(uint64_t *)pP = S + A - (intptr_t)pP;
    
    2120 2120
                        break;
    

  • rts/linker/ProddableBlocks.c
    1
    +/* -----------------------------------------------------------------------------
    
    2
    + *
    
    3
    + * (c) The GHC Team, 2025
    
    4
    + *
    
    5
    + * RTS Object Linker
    
    6
    + *
    
    7
    + * ---------------------------------------------------------------------------*/
    
    8
    +
    
    9
    +
    
    10
    +/*
    
    11
    + * Sanity checking.  For each ObjectCode, maintain a list of address ranges
    
    12
    + * which may be prodded during relocation, and abort if we try and write
    
    13
    + * outside any of these.
    
    14
    + */
    
    15
    +
    
    16
    +#include "Rts.h"
    
    17
    +#include "RtsUtils.h"
    
    18
    +#include "linker/ProddableBlocks.h"
    
    19
    +
    
    20
    +#include <stdlib.h>
    
    21
    +#include <string.h>
    
    22
    +
    
    23
    +typedef struct _ProddableBlock {
    
    24
    +    uintptr_t start;  // inclusive
    
    25
    +    uintptr_t end;    // inclusive
    
    26
    +} ProddableBlock;
    
    27
    +
    
    28
    +void
    
    29
    +initProddableBlockSet ( ProddableBlockSet* set )
    
    30
    +{
    
    31
    +    set->data = NULL;
    
    32
    +    set->capacity = 0;
    
    33
    +    set->size = 0;
    
    34
    +}
    
    35
    +
    
    36
    +void freeProddableBlocks (ProddableBlockSet *set)
    
    37
    +{
    
    38
    +    stgFree(set->data);
    
    39
    +    set->data = NULL;
    
    40
    +    set->size = 0;
    
    41
    +    set->capacity = 0;
    
    42
    +}
    
    43
    +
    
    44
    +// Binary search for the first interval with start >= value. Returns index or
    
    45
    +// size if none.
    
    46
    +static size_t
    
    47
    +findLower(const ProddableBlockSet *set, uintptr_t value)
    
    48
    +{
    
    49
    +    size_t l = 0;
    
    50
    +    size_t r = set->size;
    
    51
    +    while (l < r) {
    
    52
    +        size_t mid = l + (r - l) / 2;
    
    53
    +        if (set->data[mid].start < value) {
    
    54
    +            l = mid + 1;
    
    55
    +        } else {
    
    56
    +            r = mid;
    
    57
    +        }
    
    58
    +    }
    
    59
    +    return l;
    
    60
    +}
    
    61
    +
    
    62
    +// Check whether a given value is a member of the set.
    
    63
    +bool
    
    64
    +containsSpan ( const ProddableBlockSet *set, uintptr_t start, uintptr_t end )
    
    65
    +{
    
    66
    +    size_t i = findLower(set, start+1);
    
    67
    +    return i > 0
    
    68
    +      && set->data[i-1].start <= start
    
    69
    +      && end <= set->data[i-1].end;
    
    70
    +}
    
    71
    +
    
    72
    +void
    
    73
    +checkProddableBlock (const ProddableBlockSet *set, void *addr, size_t size )
    
    74
    +{
    
    75
    +    if (! containsSpan(set, (uintptr_t) addr, (uintptr_t) addr+size)) {
    
    76
    +        barf("checkProddableBlock: invalid fixup in runtime linker: %p", addr);
    
    77
    +    }
    
    78
    +}
    
    79
    +
    
    80
    +// Ensure capacity for at least new_capacity intervals
    
    81
    +static void
    
    82
    +ensureCapacity(ProddableBlockSet *set, size_t new_capacity) {
    
    83
    +    if (new_capacity > set->capacity) {
    
    84
    +        size_t cap = set->capacity ? set->capacity * 2 : 4;
    
    85
    +        if (cap < new_capacity) {
    
    86
    +            cap = new_capacity;
    
    87
    +        }
    
    88
    +        ProddableBlock *tmp = stgReallocBytes(set->data, cap * sizeof(ProddableBlock), "addProddableBlock");
    
    89
    +        set->data = tmp;
    
    90
    +        set->capacity = cap;
    
    91
    +    }
    
    92
    +}
    
    93
    +
    
    94
    +void
    
    95
    +addProddableBlock ( ProddableBlockSet* set, void* start_ptr, size_t size )
    
    96
    +{
    
    97
    +    const uintptr_t start = (uintptr_t) start_ptr;
    
    98
    +    const uintptr_t end = (uintptr_t) start + size;
    
    99
    +    size_t i = findLower(set, start);
    
    100
    +
    
    101
    +    // check previous interval if it is overlapping or adjacent
    
    102
    +    if (i > 0 && start <= set->data[i-1].end + 1) {
    
    103
    +        // merge with left interval
    
    104
    +        i--;
    
    105
    +        if (end > set->data[i].end) {
    
    106
    +            set->data[i].end = end;
    
    107
    +        }
    
    108
    +    } else {
    
    109
    +        // insert new interval
    
    110
    +        ensureCapacity(set, set->size + 1);
    
    111
    +        memmove(&set->data[i+1], &set->data[i], sizeof(ProddableBlock) * (set->size - i));
    
    112
    +        set->data[i].start = start;
    
    113
    +        set->data[i].end = end;
    
    114
    +        set->size++;
    
    115
    +    }
    
    116
    +
    
    117
    +    // coalesce overlaps on right
    
    118
    +    size_t j = i;
    
    119
    +    while (j < set->size && set->data[j].start <= set->data[i].end + 1) {
    
    120
    +        set->data[i].end = set->data[j].end;
    
    121
    +        j++;
    
    122
    +    }
    
    123
    +
    
    124
    +    if (j != i) {
    
    125
    +        memmove(&set->data[i+1], &set->data[j], sizeof(ProddableBlock) * (set->size - j));
    
    126
    +        set->size -= j - i - 1;
    
    127
    +    }
    
    128
    +}
    
    129
    +

  • rts/linker/ProddableBlocks.h
    1
    +/* -----------------------------------------------------------------------------
    
    2
    + *
    
    3
    + * (c) The GHC Team, 2025
    
    4
    + *
    
    5
    + * RTS Object Linker
    
    6
    + *
    
    7
    + * ---------------------------------------------------------------------------*/
    
    8
    +
    
    9
    +#pragma once
    
    10
    +
    
    11
    +#include <stdbool.h>
    
    12
    +#include <stddef.h>
    
    13
    +#include <stdint.h>
    
    14
    +
    
    15
    +// An interval set on uintptr_t.
    
    16
    +struct _ProddableBlock;
    
    17
    +
    
    18
    +typedef struct {
    
    19
    +    size_t size;
    
    20
    +    size_t capacity;
    
    21
    +    // sorted list of disjoint (start,end) pairs
    
    22
    +    struct _ProddableBlock *data;
    
    23
    +} ProddableBlockSet;
    
    24
    +
    
    25
    +void initProddableBlockSet ( ProddableBlockSet* set );
    
    26
    +
    
    27
    +// Insert an interval.
    
    28
    +void addProddableBlock ( ProddableBlockSet* set, void* start, size_t size );
    
    29
    +
    
    30
    +// Check that an address belongs to the set.
    
    31
    +void checkProddableBlock (const ProddableBlockSet *set, void *addr, size_t size );
    
    32
    +
    
    33
    +
    
    34
    +// Free a set.
    
    35
    +void freeProddableBlocks (ProddableBlockSet *set);
    
    36
    +
    
    37
    +// For testing.
    
    38
    +bool containsSpan ( const ProddableBlockSet *set, uintptr_t start, uintptr_t end );

  • rts/rts.cabal
    ... ... @@ -491,6 +491,7 @@ library
    491 491
                      linker/MachO.c
    
    492 492
                      linker/macho/plt.c
    
    493 493
                      linker/macho/plt_aarch64.c
    
    494
    +                 linker/ProddableBlocks.c
    
    494 495
                      linker/PEi386.c
    
    495 496
                      linker/SymbolExtras.c
    
    496 497
                      linker/elf_got.c