| 617 | | } |
| 618 | | |
| 619 | | |
| 620 | | /* Add a symbol to 0 symbol list */ |
| 621 | | |
| 622 | | static struct weaksym *add_weak (const char *symname, const char *modname) |
| 623 | | { |
| 624 | | struct weaksym *newsym = xmalloc (sizeof (struct weaksym)); |
| 625 | | newsym->name = xstrdup (symname); |
| 626 | | newsym->module = xstrdup (modname); |
| 627 | | newsym->used = 0; |
| 628 | | newsym->next = NULL; |
| 629 | | *weak_symbol_top = newsym; |
| 630 | | weak_symbol_top = &newsym->next; |
| 631 | | weak_list_altered = 1; |
| 632 | | return newsym; |
| 633 | | } |
| 634 | | |
| 635 | | |
| 636 | | /* Load the weak symbols table from the weaksyms.omf file. |
| 637 | | * We emulate the weak symbol functionality in the following way: |
| 638 | | * first time we encounter a weak symbol, we mark it as "strong" |
| 639 | | * and remember the first object file where it was encountered. |
| 640 | | * Then when another instance of this weak symbol is encountered |
| 641 | | * the output file name is checked; if it is a different object file, |
| 642 | | * the symbol is marked as local. Otherwise it is marked as strong. |
| 643 | | * Finally, when we find any external references to this symbol, they |
| 644 | | * are marked as "OMF weak reference", e.g. the N_WEAKU type |
| 645 | | * (which is quite different from a.out weaks, thats why we have |
| 646 | | * to dig all that mess!). Alas, this mechanism can require multi-pass |
| 647 | | * builds for complex cases... |
| 648 | | */ |
| 649 | | |
| 650 | | static void weak_load (void) |
| 651 | | { |
| 652 | | FILE *wf; |
| 653 | | char line [1024]; |
| 654 | | |
| 655 | | |
| 656 | | /* Find and open the weak symbol list file |
| 657 | | #483: If not present we'll use the new method. */ |
| 658 | | weak_list_filename = getenv ("GCC_WEAKSYMS"); |
| 659 | | if (!weak_list_filename) |
| 660 | | return ; |
| 661 | | if (opt_w) |
| 662 | | return; |
| 663 | | wf = fopen (weak_list_filename, "r"); |
| 664 | | if (!wf) |
| 665 | | return; |
| 666 | | |
| 667 | | /* Every line of the file contains something like: |
| 668 | | __symbol:object_file |
| 669 | | or just |
| 670 | | __symbol |
| 671 | | */ |
| 672 | | |
| 673 | | while (fgets (line, sizeof (line), wf)) |
| 674 | | { |
| 675 | | char *eol = strchr (line, 0); |
| 676 | | while ((eol > line) && (isspace (eol [-1]))) |
| 677 | | eol--; |
| 678 | | *eol = 0; |
| 679 | | char *sep = strchr (line, ':'); |
| 680 | | if (!sep) |
| 681 | | { |
| 682 | | fprintf (stderr, "WARNING: bad line `%s' in weak symbol list file `%s'\n", |
| 683 | | line, weak_list_filename); |
| 684 | | continue; |
| 685 | | } |
| 686 | | |
| 687 | | *sep = 0; |
| 688 | | add_weak (line, sep + 1); |
| 689 | | } |
| 690 | | |
| 691 | | fclose (wf); |
| 692 | | |
| 693 | | /* Mark the list as unmodified */ |
| 694 | | weak_list_altered = 0; |
| 695 | | } |
| 696 | | |
| 697 | | |
| 698 | | /* Save the weak symbol list */ |
| 699 | | |
| 700 | | static void weak_save (void) |
| 701 | | { |
| 702 | | FILE *wf; |
| 703 | | struct weaksym *wsym; |
| 704 | | |
| 705 | | if (opt_w) |
| 706 | | return; |
| 707 | | |
| 708 | | /* Find and open the weak symbol list file */ |
| 709 | | wf = fopen (weak_list_filename, "w"); |
| 710 | | if (!wf) |
| 711 | | return; |
| 712 | | |
| 713 | | for (wsym = weak_symbol_list; wsym; wsym = wsym->next) |
| 714 | | fprintf (wf, "%s:%s\n", wsym->name, wsym->module); |
| 715 | | |
| 716 | | fclose (wf); |
| 717 | | } |
| 718 | | |
| 719 | | |
| 720 | | /* Free the weak symbol list */ |
| 721 | | |
| 722 | | static void weak_free (void) |
| 723 | | { |
| 724 | | struct weaksym *cur = weak_symbol_list; |
| 725 | | while (cur) |
| 726 | | { |
| 727 | | struct weaksym *next = cur->next; |
| 728 | | free (cur->name); |
| 729 | | free (cur); |
| 730 | | free (cur->module); |
| 731 | | cur = next; |
| 732 | | } |
| 733 | | weak_symbol_list = NULL; |
| 734 | | } |
| 735 | | |
| 736 | | |
| 737 | | /* Find if a symbol is weak */ |
| 738 | | |
| 739 | | static struct weaksym *is_weak (const char *symname) |
| 740 | | { |
| 741 | | struct weaksym *wsym; |
| 742 | | for (wsym = weak_symbol_list; wsym; wsym = wsym->next) |
| 743 | | if (!strcmp (symname, wsym->name)) |
| 744 | | return wsym; |
| 745 | | return NULL; |
| 1217 | | /* Check all external symbol references for weakness; if a symbol is weak, |
| 1218 | | mark it as N_WEAKU so that it is later writen within a WKEXT record. |
| 1219 | | Also we convert a.out-style weak symbols here as normal public symbols, |
| 1220 | | as the sense of weak is reverse in OMF |
| 1221 | | |
| 1222 | | Weak Hack Method 1. |
| 1223 | | */ |
| 1224 | | |
| 1225 | | static void weak_process (void) |
| 1226 | | { |
| 1227 | | int i; |
| 1228 | | |
| 1229 | | if (!weak_list_filename) |
| 1230 | | return; |
| 1231 | | |
| 1232 | | #define SETTYPE(t) ((struct nlist *)sym_ptr)[i].n_type = t |
| 1233 | | |
| 1234 | | for (i = 0; i < sym_count; ++i) |
| 1235 | | if ((sym_ptr[i].n_type >= N_WEAKA) && (sym_ptr[i].n_type <= N_WEAKB)) |
| 1236 | | { |
| 1237 | | const char *name = (const char *)(str_ptr + sym_ptr[i].n_un.n_strx); |
| 1238 | | |
| 1239 | | int public = N_EXT; |
| 1240 | | |
| 1241 | | /* Add the symbol to weak list if not already */ |
| 1242 | | struct weaksym *wsym = is_weak (name); |
| 1243 | | if (!wsym) |
| 1244 | | wsym = add_weak (name, out_fname); |
| 1245 | | else if (strcmp (out_fname, wsym->module) || wsym->used) |
| 1246 | | public = 0; |
| 1247 | | /* If the symbol is exported more than once (e.g. from an archive), |
| 1248 | | export just the first instance... */ |
| 1249 | | wsym->used = 1; |
| 1250 | | |
| 1251 | | /* Now convert it to a normal public symbol */ |
| 1252 | | switch (sym_ptr[i].n_type) |
| 1253 | | { |
| 1254 | | case N_WEAKA: SETTYPE (N_ABS | public); break; |
| 1255 | | case N_WEAKT: SETTYPE (N_TEXT | public); break; |
| 1256 | | case N_WEAKD: SETTYPE (N_DATA | public); break; |
| 1257 | | case N_WEAKB: SETTYPE (N_BSS | public); break; |
| 1258 | | } |
| 1259 | | } |
| 1260 | | #if 0 |
| 1261 | | else if ((sym_ptr[i].n_type & N_EXT) && is_weak (str_ptr + sym_ptr[i].n_un.n_strx)) |
| 1262 | | { |
| 1263 | | /* Convert a external reference to N_WEAKU */ |
| 1264 | | /* P.S. As experiments show, WKEXT works somewhat strangely |
| 1265 | | with LINK386 (sometimes such external references are left |
| 1266 | | unresolved, even that they could be resolved), thus the |
| 1267 | | following line is commented out */ |
| 1268 | | /*SETTYPE (N_WEAKU);*/ |
| 1269 | | } |
| 1270 | | #endif |
| 1271 | | #undef SETTYPE |
| 1272 | | } |
| 1273 | | |
| 1274 | | |
| 1562 | | write_pubdef1 (N_ABS, 0, FALSE, 0); |
| 1563 | | write_pubdef1 (N_ABS, 0, TRUE, 0); |
| 1564 | | write_pubdef1 (N_TEXT, text_index, FALSE, 0); |
| 1565 | | write_pubdef1 (N_TEXT, text_index, TRUE, 0); |
| 1566 | | write_pubdef1 (N_DATA, udat_index, FALSE, text_size); |
| 1567 | | write_pubdef1 (N_DATA, udat_index, TRUE, text_size); |
| 1568 | | write_pubdef1 (N_BSS, bss_index, FALSE, text_size + data_size); |
| 1569 | | write_pubdef1 (N_BSS, bss_index, TRUE, text_size + data_size); |
| 1570 | | if (!weak_list_filename) |
| 1571 | | { |
| 1572 | | write_pubdef1 (N_WEAKA, 0, FALSE, 0); |
| 1573 | | write_pubdef1 (N_WEAKA, 0, TRUE, 0); |
| 1574 | | write_pubdef1 (N_WEAKT, text_index, FALSE, 0); |
| 1575 | | write_pubdef1 (N_WEAKT, text_index, TRUE, 0); |
| 1576 | | write_pubdef1 (N_WEAKD, udat_index, FALSE, text_size); |
| 1577 | | write_pubdef1 (N_WEAKD, udat_index, TRUE, text_size); |
| 1578 | | write_pubdef1 (N_WEAKB, bss_index, FALSE, text_size + data_size); |
| 1579 | | write_pubdef1 (N_WEAKB, bss_index, TRUE, text_size + data_size); |
| 1580 | | } |
| | 1348 | write_pubdef1 (N_ABS, 0, FALSE, 0); |
| | 1349 | write_pubdef1 (N_ABS, 0, TRUE, 0); |
| | 1350 | write_pubdef1 (N_TEXT, text_index, FALSE, 0); |
| | 1351 | write_pubdef1 (N_TEXT, text_index, TRUE, 0); |
| | 1352 | write_pubdef1 (N_DATA, udat_index, FALSE, text_size); |
| | 1353 | write_pubdef1 (N_DATA, udat_index, TRUE, text_size); |
| | 1354 | write_pubdef1 (N_BSS, bss_index, FALSE, text_size + data_size); |
| | 1355 | write_pubdef1 (N_BSS, bss_index, TRUE, text_size + data_size); |
| | 1356 | write_pubdef1 (N_WEAKA, 0, FALSE, 0); |
| | 1357 | write_pubdef1 (N_WEAKA, 0, TRUE, 0); |
| | 1358 | write_pubdef1 (N_WEAKT, text_index, FALSE, 0); |
| | 1359 | write_pubdef1 (N_WEAKT, text_index, TRUE, 0); |
| | 1360 | write_pubdef1 (N_WEAKD, udat_index, FALSE, text_size); |
| | 1361 | write_pubdef1 (N_WEAKD, udat_index, TRUE, text_size); |
| | 1362 | write_pubdef1 (N_WEAKB, bss_index, FALSE, text_size + data_size); |
| | 1363 | write_pubdef1 (N_WEAKB, bss_index, TRUE, text_size + data_size); |