Marge Bot pushed to branch master at Glasgow Haskell Compiler / GHC
Commits:
-
ad25af90
by Sylvain Henry at 2026-03-06T06:30:33-05:00
11 changed files:
- rts/Linker.c
- rts/LinkerInternals.h
- rts/linker/Elf.c
- rts/linker/MachO.c
- rts/linker/PEi386.c
- testsuite/tests/rts/linker/Makefile
- + testsuite/tests/rts/linker/T6107.hs
- + testsuite/tests/rts/linker/T6107.stdout
- + testsuite/tests/rts/linker/T6107_sym1.s
- + testsuite/tests/rts/linker/T6107_sym2.s
- testsuite/tests/rts/linker/all.T
Changes:
| ... | ... | @@ -268,6 +268,7 @@ int ghciInsertSymbolTable( |
| 268 | 268 | SymbolAddr* data,
|
| 269 | 269 | SymStrength strength,
|
| 270 | 270 | SymType type,
|
| 271 | + unsigned long size,
|
|
| 271 | 272 | ObjectCode *owner)
|
| 272 | 273 | {
|
| 273 | 274 | RtsSymbolInfo *pinfo = lookupStrHashTable(table, key);
|
| ... | ... | @@ -278,6 +279,7 @@ int ghciInsertSymbolTable( |
| 278 | 279 | pinfo->owner = owner;
|
| 279 | 280 | pinfo->strength = strength;
|
| 280 | 281 | pinfo->type = type;
|
| 282 | + pinfo->size = size;
|
|
| 281 | 283 | insertStrHashTable(table, key, pinfo);
|
| 282 | 284 | return 1;
|
| 283 | 285 | }
|
| ... | ... | @@ -290,6 +292,7 @@ int ghciInsertSymbolTable( |
| 290 | 292 | pinfo->owner = owner;
|
| 291 | 293 | pinfo->strength = strength;
|
| 292 | 294 | pinfo->type = type;
|
| 295 | + pinfo->size = size;
|
|
| 293 | 296 | return 1;
|
| 294 | 297 | }
|
| 295 | 298 | /* We were asked to discard the symbol on duplicates, do so quietly. */
|
| ... | ... | @@ -318,6 +321,7 @@ int ghciInsertSymbolTable( |
| 318 | 321 | /* The existing symbol is weak with a zero value; replace it with the new symbol. */
|
| 319 | 322 | pinfo->value = data;
|
| 320 | 323 | pinfo->owner = owner;
|
| 324 | + pinfo->size = size;
|
|
| 321 | 325 | return 1;
|
| 322 | 326 | }
|
| 323 | 327 | else if (strength == STRENGTH_WEAK)
|
| ... | ... | @@ -336,6 +340,7 @@ int ghciInsertSymbolTable( |
| 336 | 340 | pinfo->value = data;
|
| 337 | 341 | pinfo->owner = owner;
|
| 338 | 342 | pinfo->strength = strength;
|
| 343 | + pinfo->size = size;
|
|
| 339 | 344 | return 1;
|
| 340 | 345 | }
|
| 341 | 346 | else if ( pinfo->owner
|
| ... | ... | @@ -360,6 +365,7 @@ int ghciInsertSymbolTable( |
| 360 | 365 | pinfo->value = data;
|
| 361 | 366 | pinfo->owner = owner;
|
| 362 | 367 | pinfo->strength = strength;
|
| 368 | + pinfo->size = size;
|
|
| 363 | 369 | }
|
| 364 | 370 | |
| 365 | 371 | return 1;
|
| ... | ... | @@ -477,7 +483,7 @@ initLinker_ (int retain_cafs) |
| 477 | 483 | IF_DEBUG(linker, debugBelch("initLinker: inserting rts symbol %s, %p\n", sym->lbl, sym->addr));
|
| 478 | 484 | if (! ghciInsertSymbolTable(WSTR("(GHCi built-in symbols)"),
|
| 479 | 485 | symhash, sym->lbl, sym->addr,
|
| 480 | - sym->strength, sym->type, NULL)) {
|
|
| 486 | + sym->strength, sym->type, 0, NULL)) {
|
|
| 481 | 487 | barf("ghciInsertSymbolTable failed");
|
| 482 | 488 | }
|
| 483 | 489 | }
|
| ... | ... | @@ -495,7 +501,7 @@ initLinker_ (int retain_cafs) |
| 495 | 501 | IF_DEBUG(linker, debugBelch("initLinker: inserting extra rts symbol %s, %p\n", sym->lbl, sym->addr));
|
| 496 | 502 | if (! ghciInsertSymbolTable(WSTR("(GHCi built-in symbols)"),
|
| 497 | 503 | symhash, sym->lbl, sym->addr,
|
| 498 | - sym->strength, sym->type, NULL)) {
|
|
| 504 | + sym->strength, sym->type, 0, NULL)) {
|
|
| 499 | 505 | barf("ghciInsertSymbolTable failed");
|
| 500 | 506 | }
|
| 501 | 507 | }
|
| ... | ... | @@ -506,7 +512,7 @@ initLinker_ (int retain_cafs) |
| 506 | 512 | if (! ghciInsertSymbolTable(WSTR("(GHCi built-in symbols)"), symhash,
|
| 507 | 513 | MAYBE_LEADING_UNDERSCORE_STR("newCAF"),
|
| 508 | 514 | retain_cafs ? newRetainedCAF : newGCdCAF,
|
| 509 | - HS_BOOL_FALSE, SYM_TYPE_CODE, NULL)) {
|
|
| 515 | + HS_BOOL_FALSE, SYM_TYPE_CODE, 0, NULL)) {
|
|
| 510 | 516 | barf("ghciInsertSymbolTable failed");
|
| 511 | 517 | }
|
| 512 | 518 | |
| ... | ... | @@ -778,7 +784,7 @@ HsBool removeLibrarySearchPath(HsPtr dll_path_index) |
| 778 | 784 | HsInt insertSymbol(pathchar* obj_name, SymbolName* key, SymbolAddr* data)
|
| 779 | 785 | {
|
| 780 | 786 | return ghciInsertSymbolTable(obj_name, symhash, key, data, HS_BOOL_FALSE,
|
| 781 | - SYM_TYPE_CODE, NULL);
|
|
| 787 | + SYM_TYPE_CODE, 0, NULL);
|
|
| 782 | 788 | }
|
| 783 | 789 | |
| 784 | 790 | /* -----------------------------------------------------------------------------
|
| ... | ... | @@ -1623,7 +1629,7 @@ int ocTryLoad (ObjectCode* oc) { |
| 1623 | 1629 | && !ghciInsertSymbolTable(oc->fileName, symhash, symbol.name,
|
| 1624 | 1630 | symbol.addr,
|
| 1625 | 1631 | isSymbolWeak(oc, symbol.name),
|
| 1626 | - symbol.type, oc)) {
|
|
| 1632 | + symbol.type, 0, oc)) {
|
|
| 1627 | 1633 | return 0;
|
| 1628 | 1634 | }
|
| 1629 | 1635 | }
|
| ... | ... | @@ -418,6 +418,7 @@ typedef struct _RtsSymbolInfo { |
| 418 | 418 | ObjectCode *owner;
|
| 419 | 419 | SymStrength strength;
|
| 420 | 420 | SymType type;
|
| 421 | + unsigned long size; // symbol size: only used for COMMON symbols
|
|
| 421 | 422 | } RtsSymbolInfo;
|
| 422 | 423 | |
| 423 | 424 | #include "BeginPrivate.h"
|
| ... | ... | @@ -441,6 +442,7 @@ int ghciInsertSymbolTable( |
| 441 | 442 | SymbolAddr* data,
|
| 442 | 443 | SymStrength weak,
|
| 443 | 444 | SymType type,
|
| 445 | + unsigned long size,
|
|
| 444 | 446 | ObjectCode *owner);
|
| 445 | 447 | |
| 446 | 448 | /* Lock-free version of lookupSymbol. When 'dependent' is not NULL, adds it as a
|
| ... | ... | @@ -961,7 +961,11 @@ ocGetNames_ELF ( ObjectCode* oc ) |
| 961 | 961 | for (size_t j = 0; j < symTab->n_symbols; j++) {
|
| 962 | 962 | ElfSymbol *symbol = &symTab->symbols[j];
|
| 963 | 963 | if (SHN_COMMON == symTab->symbols[j].elf_sym->st_shndx) {
|
| 964 | - common_size += symbol->elf_sym->st_size;
|
|
| 964 | + /* Skip COMMON symbols already defined by a previously-loaded
|
|
| 965 | + * object; we will reuse the existing allocation. */
|
|
| 966 | + if (!lookupStrHashTable(symhash, symTab->symbols[j].name)) {
|
|
| 967 | + common_size += symbol->elf_sym->st_size;
|
|
| 968 | + }
|
|
| 965 | 969 | }
|
| 966 | 970 | }
|
| 967 | 971 | }
|
| ... | ... | @@ -1006,17 +1010,35 @@ ocGetNames_ELF ( ObjectCode* oc ) |
| 1006 | 1010 | /* Figure out if we want to add it; if so, set ad to its
|
| 1007 | 1011 | address. Otherwise leave ad == NULL. */
|
| 1008 | 1012 | |
| 1013 | + bool common_already_defined = false;
|
|
| 1009 | 1014 | if (shndx == SHN_COMMON) {
|
| 1010 | 1015 | isLocal = false;
|
| 1011 | - CHECK(common_used < common_size);
|
|
| 1012 | - CHECK(common_mem);
|
|
| 1013 | - symbol->addr = (void*)((uintptr_t)common_mem + common_used);
|
|
| 1014 | - common_used += symbol->elf_sym->st_size;
|
|
| 1015 | - CHECK(common_used <= common_size);
|
|
| 1016 | - |
|
| 1017 | - IF_DEBUG(linker_verbose,
|
|
| 1018 | - debugBelch("COMMON symbol, size %llu name %s allocated at %p\n",
|
|
| 1019 | - (long long unsigned int) symbol->elf_sym->st_size, nm, symbol->addr));
|
|
| 1016 | + RtsSymbolInfo *existing = lookupStrHashTable(symhash, nm);
|
|
| 1017 | + if (existing != NULL) {
|
|
| 1018 | + /* COMMON symbol already allocated by a previously-loaded
|
|
| 1019 | + * object; reuse that address so relocations resolve to
|
|
| 1020 | + * the same storage. */
|
|
| 1021 | + if(symbol->elf_sym->st_size > existing->size) {
|
|
| 1022 | + barf("linker: trying to link COMMON symbols %s with incompatible sizes: previous size %llu, new size %llu\n",
|
|
| 1023 | + nm,
|
|
| 1024 | + (long long unsigned int) existing->size,
|
|
| 1025 | + (long long unsigned int) symbol->elf_sym->st_size);
|
|
| 1026 | + }
|
|
| 1027 | + symbol->addr = existing->value;
|
|
| 1028 | + common_already_defined = true;
|
|
| 1029 | + IF_DEBUG(linker_verbose,
|
|
| 1030 | + debugBelch("COMMON symbol, size %llu name %s reusing address %p\n",
|
|
| 1031 | + (long long unsigned int) symbol->elf_sym->st_size, nm, symbol->addr));
|
|
| 1032 | + } else {
|
|
| 1033 | + CHECK(common_used < common_size);
|
|
| 1034 | + CHECK(common_mem);
|
|
| 1035 | + symbol->addr = (void*)((uintptr_t)common_mem + common_used);
|
|
| 1036 | + common_used += symbol->elf_sym->st_size;
|
|
| 1037 | + CHECK(common_used <= common_size);
|
|
| 1038 | + IF_DEBUG(linker_verbose,
|
|
| 1039 | + debugBelch("COMMON symbol, size %llu name %s allocated at %p\n",
|
|
| 1040 | + (long long unsigned int) symbol->elf_sym->st_size, nm, symbol->addr));
|
|
| 1041 | + }
|
|
| 1020 | 1042 | |
| 1021 | 1043 | /* Pointless to do addProddableBlock() for this area,
|
| 1022 | 1044 | since the linker should never poke around in it. */
|
| ... | ... | @@ -1080,13 +1102,13 @@ ocGetNames_ELF ( ObjectCode* oc ) |
| 1080 | 1102 | if (symbol->addr != NULL) {
|
| 1081 | 1103 | CHECK(nm != NULL);
|
| 1082 | 1104 | /* Acquire! */
|
| 1083 | - if (!isLocal) {
|
|
| 1105 | + if (!isLocal && !common_already_defined) {
|
|
| 1084 | 1106 | |
| 1085 | 1107 | if (isWeak == HS_BOOL_TRUE) {
|
| 1086 | 1108 | setWeakSymbol(oc, nm);
|
| 1087 | 1109 | }
|
| 1088 | 1110 | if (!ghciInsertSymbolTable(oc->fileName, symhash,
|
| 1089 | - nm, symbol->addr, isWeak, sym_type, oc)
|
|
| 1111 | + nm, symbol->addr, isWeak, sym_type, symbol->elf_sym->st_size, oc)
|
|
| 1090 | 1112 | ) {
|
| 1091 | 1113 | goto fail;
|
| 1092 | 1114 | }
|
| ... | ... | @@ -1421,8 +1421,13 @@ ocGetNames_MachO(ObjectCode* oc) |
| 1421 | 1421 | if((oc->info->nlist[i].n_type & N_TYPE) == N_UNDF
|
| 1422 | 1422 | && (oc->info->nlist[i].n_value != 0))
|
| 1423 | 1423 | {
|
| 1424 | - commonSize += oc->info->nlist[i].n_value;
|
|
| 1425 | 1424 | oc->n_symbols++;
|
| 1425 | + /* Only allocate space for COMMON symbols not already
|
|
| 1426 | + * defined by a previously-loaded object. */
|
|
| 1427 | + SymbolName *nm_c = oc->info->macho_symbols[i].name;
|
|
| 1428 | + if (!lookupStrHashTable(symhash, nm_c)) {
|
|
| 1429 | + commonSize += oc->info->nlist[i].n_value;
|
|
| 1430 | + }
|
|
| 1426 | 1431 | }
|
| 1427 | 1432 | else if((oc->info->nlist[i].n_type & N_TYPE) == N_SECT)
|
| 1428 | 1433 | oc->n_symbols++;
|
| ... | ... | @@ -1436,7 +1441,7 @@ ocGetNames_MachO(ObjectCode* oc) |
| 1436 | 1441 | */
|
| 1437 | 1442 | IF_DEBUG(linker, debugBelch("ocGetNames_MachO: %d external symbols\n",
|
| 1438 | 1443 | oc->n_symbols));
|
| 1439 | - oc->symbols = stgMallocBytes(oc->n_symbols * sizeof(Symbol_t),
|
|
| 1444 | + oc->symbols = stgCallocBytes(oc->n_symbols, sizeof(Symbol_t),
|
|
| 1440 | 1445 | "ocGetNames_MachO(oc->symbols)");
|
| 1441 | 1446 | |
| 1442 | 1447 | if (oc->info->symCmd) {
|
| ... | ... | @@ -1467,6 +1472,7 @@ ocGetNames_MachO(ObjectCode* oc) |
| 1467 | 1472 | , addr
|
| 1468 | 1473 | , HS_BOOL_FALSE
|
| 1469 | 1474 | , sym_type
|
| 1475 | + , 0
|
|
| 1470 | 1476 | , oc);
|
| 1471 | 1477 | |
| 1472 | 1478 | oc->symbols[curSymbol].name = nm;
|
| ... | ... | @@ -1488,8 +1494,10 @@ ocGetNames_MachO(ObjectCode* oc) |
| 1488 | 1494 | }
|
| 1489 | 1495 | |
| 1490 | 1496 | /* setup the common storage */
|
| 1491 | - commonStorage = stgCallocBytes(1,commonSize,"ocGetNames_MachO(common symbols)");
|
|
| 1492 | - commonCounter = (unsigned long)commonStorage;
|
|
| 1497 | + if (commonSize > 0) {
|
|
| 1498 | + commonStorage = stgCallocBytes(1, commonSize, "ocGetNames_MachO(common symbols)");
|
|
| 1499 | + commonCounter = (unsigned long)commonStorage;
|
|
| 1500 | + }
|
|
| 1493 | 1501 | |
| 1494 | 1502 | if (oc->info->symCmd) {
|
| 1495 | 1503 | for (size_t i = 0; i < oc->info->n_macho_symbols; i++) {
|
| ... | ... | @@ -1499,22 +1507,47 @@ ocGetNames_MachO(ObjectCode* oc) |
| 1499 | 1507 | && (nlist->n_type & N_EXT)
|
| 1500 | 1508 | && (nlist->n_value != 0)) {
|
| 1501 | 1509 | unsigned long sz = nlist->n_value;
|
| 1502 | - |
|
| 1503 | - nlist->n_value = commonCounter;
|
|
| 1504 | - |
|
| 1505 | - /* also set the final address to the macho_symbol */
|
|
| 1506 | - oc->info->macho_symbols[i].addr = (void*)commonCounter;
|
|
| 1507 | 1510 | /* TODO: Figure out how to determine this from object */
|
| 1508 | 1511 | SymType sym_type = SYM_TYPE_CODE;
|
| 1509 | 1512 | |
| 1510 | - IF_DEBUG(linker_verbose, debugBelch("ocGetNames_MachO: inserting common symbol: %s\n", nm));
|
|
| 1511 | - ghciInsertSymbolTable(oc->fileName, symhash, nm,
|
|
| 1512 | - (void*)commonCounter, HS_BOOL_FALSE, sym_type, oc);
|
|
| 1513 | - oc->symbols[curSymbol].name = nm;
|
|
| 1514 | - oc->symbols[curSymbol].addr = oc->info->macho_symbols[i].addr;
|
|
| 1515 | - curSymbol++;
|
|
| 1513 | + RtsSymbolInfo *existing = lookupStrHashTable(symhash, nm);
|
|
| 1514 | + if (existing != NULL) {
|
|
| 1515 | + /* COMMON symbol already allocated by a previously-loaded
|
|
| 1516 | + * object; reuse that address so relocations resolve to
|
|
| 1517 | + * the same storage. */
|
|
| 1518 | + if (sz > existing->size) {
|
|
| 1519 | + barf("linker: trying to link COMMON symbols %s with"
|
|
| 1520 | + " incompatible sizes: previous size %llu,"
|
|
| 1521 | + " new size %lu\n",
|
|
| 1522 | + nm,
|
|
| 1523 | + (long long unsigned int) existing->size,
|
|
| 1524 | + sz);
|
|
| 1525 | + }
|
|
| 1526 | + nlist->n_value = (unsigned long)existing->value;
|
|
| 1527 | + oc->info->macho_symbols[i].addr = existing->value;
|
|
| 1528 | + IF_DEBUG(linker_verbose,
|
|
| 1529 | + debugBelch("ocGetNames_MachO: COMMON symbol %s"
|
|
| 1530 | + " reusing address %p\n",
|
|
| 1531 | + nm, existing->value));
|
|
| 1532 | + /* Don't add to oc->symbols: not the owner */
|
|
| 1533 | + } else {
|
|
| 1534 | + nlist->n_value = commonCounter;
|
|
| 1535 | + /* also set the final address to the macho_symbol */
|
|
| 1536 | + oc->info->macho_symbols[i].addr = (void*)commonCounter;
|
|
| 1516 | 1537 | |
| 1517 | - commonCounter += sz;
|
|
| 1538 | + IF_DEBUG(linker_verbose,
|
|
| 1539 | + debugBelch("ocGetNames_MachO: inserting common symbol: %s\n", nm));
|
|
| 1540 | + ghciInsertSymbolTable(oc->fileName, symhash, nm,
|
|
| 1541 | + (void*)commonCounter, HS_BOOL_FALSE,
|
|
| 1542 | + sym_type,
|
|
| 1543 | + sz, oc);
|
|
| 1544 | + oc->symbols[curSymbol].name = nm;
|
|
| 1545 | + oc->symbols[curSymbol].addr = oc->info->macho_symbols[i].addr;
|
|
| 1546 | + oc->symbols[curSymbol].type = sym_type;
|
|
| 1547 | + curSymbol++;
|
|
| 1548 | + |
|
| 1549 | + commonCounter += sz;
|
|
| 1550 | + }
|
|
| 1518 | 1551 | }
|
| 1519 | 1552 | }
|
| 1520 | 1553 | }
|
| ... | ... | @@ -573,7 +573,7 @@ void initLinker_PEi386(void) |
| 573 | 573 | if (!ghciInsertSymbolTable(WSTR("(GHCi/Ld special symbols)"),
|
| 574 | 574 | symhash, "__image_base__",
|
| 575 | 575 | GetModuleHandleW (NULL), HS_BOOL_TRUE,
|
| 576 | - SYM_TYPE_CODE, NULL)) {
|
|
| 576 | + SYM_TYPE_CODE, 0, NULL)) {
|
|
| 577 | 577 | barf("ghciInsertSymbolTable failed");
|
| 578 | 578 | }
|
| 579 | 579 | |
| ... | ... | @@ -1186,7 +1186,7 @@ bool checkAndLoadImportLibrary( pathchar* arch_name, char* member_name, FILE* f |
| 1186 | 1186 | SymType symType = SYM_TYPE_DUP_DISCARD | SYM_TYPE_HIDDEN;
|
| 1187 | 1187 | symType |= hdr.Type == IMPORT_OBJECT_CODE ? SYM_TYPE_CODE : SYM_TYPE_DATA;
|
| 1188 | 1188 | |
| 1189 | - if (!ghciInsertSymbolTable(dll, symhash, symbol, sym, false, symType, NULL))
|
|
| 1189 | + if (!ghciInsertSymbolTable(dll, symhash, symbol, sym, false, symType, 0, NULL))
|
|
| 1190 | 1190 | return false;
|
| 1191 | 1191 | |
| 1192 | 1192 | return true;
|
| ... | ... | @@ -1825,7 +1825,12 @@ ocGetNames_PEi386 ( ObjectCode* oc ) |
| 1825 | 1825 | if (getSymSectionNumber (info, sym) == PE_SECTION_UNDEFINED
|
| 1826 | 1826 | && getSymValue (info, sym) > 0
|
| 1827 | 1827 | && getSymStorageClass (info, sym) != IMAGE_SYM_CLASS_SECTION) {
|
| 1828 | - globalBssSize += getSymValue (info, sym);
|
|
| 1828 | + /* Only count COMMON symbols not already defined by a
|
|
| 1829 | + * previously-loaded object; we will reuse their allocation. */
|
|
| 1830 | + SymbolName *nm = get_sym_name (getSymShortName (info, sym), oc);
|
|
| 1831 | + if (!lookupStrHashTable(symhash, nm)) {
|
|
| 1832 | + globalBssSize += getSymValue (info, sym);
|
|
| 1833 | + }
|
|
| 1829 | 1834 | }
|
| 1830 | 1835 | i += getSymNumberOfAuxSymbols (info, sym);
|
| 1831 | 1836 | }
|
| ... | ... | @@ -1859,6 +1864,8 @@ ocGetNames_PEi386 ( ObjectCode* oc ) |
| 1859 | 1864 | uint8_t symStorageClass = getSymStorageClass (info, sym);
|
| 1860 | 1865 | SymbolAddr *addr = NULL;
|
| 1861 | 1866 | bool isWeak = false;
|
| 1867 | + bool common_already_defined = false;
|
|
| 1868 | + unsigned long symSize = 0;
|
|
| 1862 | 1869 | SymbolName *sname = get_sym_name (getSymShortName (info, sym), oc);
|
| 1863 | 1870 | |
| 1864 | 1871 | uint32_t secNumber = getSymSectionNumber (info, sym);
|
| ... | ... | @@ -1959,10 +1966,31 @@ ocGetNames_PEi386 ( ObjectCode* oc ) |
| 1959 | 1966 | }
|
| 1960 | 1967 | else if ( secNumber == IMAGE_SYM_UNDEFINED && symValue > 0) {
|
| 1961 | 1968 | /* This symbol isn't in any section at all, ie, global bss.
|
| 1962 | - Allocate zeroed space for it from the BSS section */
|
|
| 1963 | - addr = bss;
|
|
| 1964 | - bss = (SymbolAddr*)((StgWord)bss + (StgWord)symValue);
|
|
| 1965 | - IF_DEBUG(linker_verbose, debugBelch("bss symbol @ %p %u\n", addr, symValue));
|
|
| 1969 | + Allocate zeroed space for it from the BSS section, unless a
|
|
| 1970 | + previously-loaded object already allocated storage for it. */
|
|
| 1971 | + RtsSymbolInfo *existing = lookupStrHashTable(symhash, sname);
|
|
| 1972 | + if (existing != NULL) {
|
|
| 1973 | + /* COMMON symbol already allocated by a previously-loaded
|
|
| 1974 | + * object; reuse that address so relocations resolve to
|
|
| 1975 | + * the same storage. */
|
|
| 1976 | + if (symValue > existing->size) {
|
|
| 1977 | + barf("linker: trying to link COMMON symbols %s with"
|
|
| 1978 | + " incompatible sizes: previous size %llu,"
|
|
| 1979 | + " new size %u\n",
|
|
| 1980 | + sname,
|
|
| 1981 | + (long long unsigned int) existing->size,
|
|
| 1982 | + symValue);
|
|
| 1983 | + }
|
|
| 1984 | + addr = existing->value;
|
|
| 1985 | + common_already_defined = true;
|
|
| 1986 | + IF_DEBUG(linker_verbose,
|
|
| 1987 | + debugBelch("bss symbol reusing @ %p %u\n", addr, symValue));
|
|
| 1988 | + } else {
|
|
| 1989 | + addr = bss;
|
|
| 1990 | + bss = (SymbolAddr*)((StgWord)bss + (StgWord)symValue);
|
|
| 1991 | + symSize = (unsigned long)symValue;
|
|
| 1992 | + IF_DEBUG(linker_verbose, debugBelch("bss symbol @ %p %u\n", addr, symValue));
|
|
| 1993 | + }
|
|
| 1966 | 1994 | }
|
| 1967 | 1995 | else if (section && section->kind == SECTIONKIND_BFD_IMPORT_LIBRARY) {
|
| 1968 | 1996 | /* Disassembly of section .idata$5:
|
| ... | ... | @@ -1990,7 +2018,7 @@ ocGetNames_PEi386 ( ObjectCode* oc ) |
| 1990 | 2018 | type = has_code_section ? SYM_TYPE_CODE : SYM_TYPE_DATA;
|
| 1991 | 2019 | type |= SYM_TYPE_DUP_DISCARD;
|
| 1992 | 2020 | if (!ghciInsertSymbolTable(oc->fileName, symhash, sname,
|
| 1993 | - addr, false, type, oc)) {
|
|
| 2021 | + addr, false, type, 0, oc)) {
|
|
| 1994 | 2022 | releaseOcInfo (oc);
|
| 1995 | 2023 | stgFree (oc->image);
|
| 1996 | 2024 | oc->image = NULL;
|
| ... | ... | @@ -2073,7 +2101,7 @@ ocGetNames_PEi386 ( ObjectCode* oc ) |
| 2073 | 2101 | type |= SYM_TYPE_HIDDEN;
|
| 2074 | 2102 | |
| 2075 | 2103 | if (!ghciInsertSymbolTable(oc->fileName, symhash, sname,
|
| 2076 | - addr, false, type, oc))
|
|
| 2104 | + addr, false, type, 0, oc))
|
|
| 2077 | 2105 | return false;
|
| 2078 | 2106 | |
| 2079 | 2107 | break;
|
| ... | ... | @@ -2083,6 +2111,7 @@ ocGetNames_PEi386 ( ObjectCode* oc ) |
| 2083 | 2111 | }
|
| 2084 | 2112 | |
| 2085 | 2113 | if ((addr != NULL || isWeak)
|
| 2114 | + && !common_already_defined
|
|
| 2086 | 2115 | && (!section || (section && section->kind != SECTIONKIND_IMPORT))) {
|
| 2087 | 2116 | /* debugBelch("addSymbol %p `%s' Weak:%lld \n", addr, sname, isWeak); */
|
| 2088 | 2117 | sname = strdup (sname);
|
| ... | ... | @@ -2098,7 +2127,7 @@ ocGetNames_PEi386 ( ObjectCode* oc ) |
| 2098 | 2127 | }
|
| 2099 | 2128 | |
| 2100 | 2129 | if (! ghciInsertSymbolTable(oc->fileName, symhash, sname, addr,
|
| 2101 | - isWeak, type, oc))
|
|
| 2130 | + isWeak, type, symSize, oc))
|
|
| 2102 | 2131 | return false;
|
| 2103 | 2132 | } else {
|
| 2104 | 2133 | /* We're skipping the symbol, but if we ever load this
|
| ... | ... | @@ -152,3 +152,10 @@ T25191: |
| 152 | 152 | "$(TEST_HC)" -c T25191_foo2.c -o foo2.o -v0
|
| 153 | 153 | "$(TEST_HC)" T25191.hs -v0
|
| 154 | 154 | ./T25191
|
| 155 | + |
|
| 156 | +.PHONY: T6107
|
|
| 157 | +T6107:
|
|
| 158 | + "$(TEST_HC)" -c T6107_sym1.s -o T6107_sym1.o -v0
|
|
| 159 | + "$(TEST_HC)" -c T6107_sym2.s -o T6107_sym2.o -v0
|
|
| 160 | + "$(TEST_HC)" $(TEST_HC_OPTS) T6107.hs -o T6107 -v0
|
|
| 161 | + ./T6107 |
| 1 | +{-# LANGUAGE ForeignFunctionInterface, CPP #-}
|
|
| 2 | +-- Test that the RTS linker merges COMMON symbols from multiple object files.
|
|
| 3 | +-- Without the fix, loadObj of the second .o fails with a duplicate symbol error.
|
|
| 4 | +import Foreign.C.String
|
|
| 5 | +import Control.Monad
|
|
| 6 | + |
|
| 7 | +-- Type of paths is different on Windows
|
|
| 8 | +#if defined(mingw32_HOST_OS)
|
|
| 9 | +type PathString = CWString
|
|
| 10 | +withPathString = withCWString
|
|
| 11 | +#else
|
|
| 12 | +type PathString = CString
|
|
| 13 | +withPathString = withCString
|
|
| 14 | +#endif
|
|
| 15 | + |
|
| 16 | +main :: IO ()
|
|
| 17 | +main = do
|
|
| 18 | + initLinker
|
|
| 19 | + r1 <- withPathString "T6107_sym1.o" loadObj
|
|
| 20 | + when (r1 /= 1) $ error "loadObj T6107_sym1.o failed"
|
|
| 21 | + r2 <- withPathString "T6107_sym2.o" loadObj
|
|
| 22 | + when (r2 /= 1) $ error "loadObj T6107_sym2.o failed"
|
|
| 23 | + r <- resolveObjs
|
|
| 24 | + when (r /= 1) $ error "resolveObjs failed"
|
|
| 25 | + putStrLn "OK"
|
|
| 26 | + |
|
| 27 | +foreign import ccall "initLinker" initLinker :: IO ()
|
|
| 28 | +foreign import ccall "loadObj" loadObj :: PathString -> IO Int
|
|
| 29 | +foreign import ccall "resolveObjs" resolveObjs :: IO Int |
| 1 | +OK |
| 1 | +.comm shared_var, 4 |
| 1 | +.comm shared_var, 4 |
| ... | ... | @@ -181,3 +181,11 @@ test('T25191', |
| 181 | 181 | when(opsys('mingw32'), expect_broken(25191)) # not supported in the PE linker yet
|
| 182 | 182 | ],
|
| 183 | 183 | makefile_test, ['T25191'])
|
| 184 | + |
|
| 185 | + |
|
| 186 | +# Test that COMMON symbols from multiple object files are merged correctly
|
|
| 187 | +test('T6107',
|
|
| 188 | + [req_rts_linker,
|
|
| 189 | + extra_files(['T6107_sym1.s', 'T6107_sym2.s'])
|
|
| 190 | + ],
|
|
| 191 | + makefile_test, ['T6107']) |